API reference

Projects

Every path is under https://impartire.com/api/v1. Generated from the API’s own contract, openapi.json (OpenAPI 3.1), which you can load into any OpenAPI tool. Errors are Problems — see Conventions.

GET/api/v1/projects

List the org's projects

Ordered by name unless sort says otherwise. To poll for changes, pass updated_after with the newest updated_at you have seen and sort=-updated_at (or updated_at). A deleted project leaves the list.

Scopes: projects:read

Parameters
  • limitquery · integer

    Page size, default 50. Values above 100 are treated as 100.

  • cursorquery · string

    next_cursor from the previous page, with the other parameters unchanged.

  • parent_idquery · string (uuid)

    Only the direct children of this project.

  • updated_afterquery · string (date-time)

    Only projects changed strictly after this instant (ISO 8601 with offset), compared to the millisecond — poll with the newest updated_at you have seen (that project does not come back), sorted -updated_at or updated_at.

  • sortquery · "name" | "-name" | "updated_at" | "-updated_at"

    Sort key; a leading - is descending. Default name. Ties break on id.

Response 200ProjectList
  • dataarray of Projectrequired
    • idstring (uuid)required
    • namestringrequired
    • descriptionstring or nullrequired
    • parent_idstring (uuid) or nullrequired
    • visibilitystringrequired

      open | closed | private

    • project_typeobject or nullrequired

      The project's type (the org's project types: production, season, campaign…), or null if untyped.

      • idstring (uuid)required
      • namestringrequired
    • created_atstring (date-time)required
    • updated_atstring (date-time)required

      When its name, description or type last changed.

  • next_cursorstring or nullrequired

    Pass as cursor to get the next page; null means this is the last page.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope — the key lacks a required scope.
  • 404 not-found.
  • 422 validation — a bad limit, parent_id, updated_after, sort or cursor.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.

POST/api/v1/projects

Create a project, optionally typed and under a parent

A root project (no parent_id) is born Closed — org members see that it exists, admitted teams open it; a sub-project inherits its parent's access. The credential is the project's owner: for an API key, the key's service principal. Typed projects follow the org's hierarchy rules.

Scopes: projects:write

Parameters
  • Idempotency-Keyheader · string

    Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request bodyCreateProjectRequest
  • namestringrequired
  • descriptionstring or null
  • parent_idstring (uuid)

    Create it as a sub-project of this project (GET /api/v1/projects). Omit for a root project (a production), which is born Closed: org members see it exists, admitted teams open it.

  • project_type_idstring (uuid)

    One of the org's project types. When the parent is typed too, the org's hierarchy rules must allow this type under the parent's (a root needs a rule allowing the type at the root); 422 invalid-hierarchy otherwise.

Response 201Project
  • idstring (uuid)required
  • namestringrequired
  • descriptionstring or nullrequired
  • parent_idstring (uuid) or nullrequired
  • visibilitystringrequired

    open | closed | private

  • project_typeobject or nullrequired

    The project's type (the org's project types: production, season, campaign…), or null if untyped.

    • idstring (uuid)required
    • namestringrequired
  • created_atstring (date-time)required
  • updated_atstring (date-time)required

    When its name, description or type last changed.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope — the key lacks a required scope.
  • 404 not-found.
  • 409 idempotency-in-flight.
  • 422 validation (name, description, parent_id, project_type_id), invalid-hierarchy, or idempotency-mismatch.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 authorization-write-failed — the project's permissions could not be written, so it was rolled back; or internal.

GET/api/v1/projects/{id}

Get one project

Scopes: projects:read

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • If-None-Matchheader · string

    An ETag from a previous response; 304 if unchanged.

Response 200Project
  • idstring (uuid)required
  • namestringrequired
  • descriptionstring or nullrequired
  • parent_idstring (uuid) or nullrequired
  • visibilitystringrequired

    open | closed | private

  • project_typeobject or nullrequired

    The project's type (the org's project types: production, season, campaign…), or null if untyped.

    • idstring (uuid)required
    • namestringrequired
  • created_atstring (date-time)required
  • updated_atstring (date-time)required

    When its name, description or type last changed.

Other responses
  • 304 Not modified — the ETag in If-None-Match is current.
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope — the key lacks a required scope.
  • 404 not-found.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.

PATCH/api/v1/projects/{id}

Rename, describe or retype a project

If-Match is required: send the ETag from the last GET (or from the create). A retype must fit the org's hierarchy rules under the parent's type and above each sub-project's type. Moving a project is POST /projects/{id}/move (guarded); changing its visibility is done in the app.

Scopes: projects:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • If-Matchheader · stringrequired

    The project's ETag.

Request bodyUpdateProjectRequest

At least one of name, description, project_type_id. Moving a project and changing its visibility are not in v1.

  • namestring
  • descriptionstring or null

    null clears it.

  • project_type_idstring (uuid) or null

    Retype the project; null makes it untyped. The org's hierarchy rules must allow the type under its parent's type (or at the root) and above each sub-project's type; 422 invalid-hierarchy otherwise.

Response 200Project
  • idstring (uuid)required
  • namestringrequired
  • descriptionstring or nullrequired
  • parent_idstring (uuid) or nullrequired
  • visibilitystringrequired

    open | closed | private

  • project_typeobject or nullrequired

    The project's type (the org's project types: production, season, campaign…), or null if untyped.

    • idstring (uuid)required
    • namestringrequired
  • created_atstring (date-time)required
  • updated_atstring (date-time)required

    When its name, description or type last changed.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope — the key lacks a required scope.
  • 404 not-found.
  • 412 precondition-failed — If-Match is stale; etag in the body is the current one.
  • 422 validation (empty body, name, description, project_type_id), or invalid-hierarchy.
  • 428 precondition-required — no If-Match.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.

POST/api/v1/projects/{id}/access

Give a member, team or role access to a project (guarded)

A guarded action (ADR 0081): it changes who can see the project. The app's own write runs, with its checks and words. **An API key's write happens at once.** **An OAuth token's does not**: 202 with a Confirmation naming the project and who, by name; once its person confirms it in impartire it runs as them, every check again. Its person must manage the project (project manage; no platform-admin bypass). The subject must be a member, team or role of the org (422), a team not archived and a subject not denied on the project (409: lift the deny first). A team's or role's grant follows its membership. Audited: a project.access_granted event.

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • Idempotency-Keyheader · string

    Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request bodyGrantProjectAccessRequest
  • subject_type"member" | "team" | "role"required

    member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

  • subject_idstring (uuid)required

    The member's principal id (GET /api/v1/members), or the team's or role's id — of this org.

  • level"viewer" | "asset_contributor" | "asset_purger" | "contributor" | "manager"required

    viewer: read the project and everything filed under it. contributor: edit the project too. manager: administer it, including who has access. asset_contributor: edit the assets filed under it WITHOUT reading the project. asset_purger: delete them, likewise.

Response 201ProjectGrant

A project access grant: who, at which level.

  • projectobjectrequired

    The project.

    • idstring (uuid)required
    • namestringrequired
  • subjectobjectrequired
    • type"member" | "team" | "role"required

      member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

    • idstring (uuid)required

      The member's principal id, or the team's or role's id.

    • namestring or nullrequired

      The member's name, or the team's or role's. Null when it is no longer in the org.

  • level"viewer" | "asset_contributor" | "asset_purger" | "contributor" | "manager"required

    viewer: read the project and everything filed under it. contributor: edit the project too. manager: administer it, including who has access. asset_contributor: edit the assets filed under it WITHOUT reading the project. asset_purger: delete them, likewise.

Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person can open the project but not manage it.
  • 404 not-found.
  • 409 conflict — an archived team, or a subject denied on the project; confirmation-pending; or idempotency-in-flight.
  • 422 validation (a bad field; subject_id not of the org), or idempotency-mismatch (an OAuth token may not send Idempotency-Key).
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the permission service could not be reached; nothing changed.

DELETE/api/v1/projects/{id}/access

Take one access grant on a project away (guarded)

A guarded action (ADR 0081): it changes who can see the project. The app's own write runs, with its checks and words. **An API key's write happens at once.** **An OAuth token's does not**: 202 with a Confirmation naming the project and who, by name; once its person confirms it in impartire it runs as them, every check again. Its person must manage the project. Names the grant by subject_type, subject_id and level; a subject that has since left the org can still be revoked. 404 when there is no such grant (nothing changed). Audited: a project.access_revoked event.

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • subject_typequery · "member" | "team" | "role"required

    member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

  • subject_idquery · string (uuid)required

    The subject the grant names.

  • levelquery · "viewer" | "asset_contributor" | "asset_purger" | "contributor" | "manager"required

    viewer: read the project and everything filed under it. contributor: edit the project too. manager: administer it, including who has access. asset_contributor: edit the assets filed under it WITHOUT reading the project. asset_purger: delete them, likewise.

Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 204 An API key's revoke: the grant is gone.
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person cannot manage the project.
  • 404 not-found.
  • 409 confirmation-pending.
  • 422 validation — a missing or bad subject_type, subject_id or level.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the permission service could not be reached; nothing changed.

POST/api/v1/projects/{id}/deny

Deny a member, team or role on a project (guarded)

A guarded action (ADR 0081): it changes who can see the project. The app's own write runs, with its checks and words. **An API key's write happens at once.** **An OAuth token's does not**: 202 with a Confirmation naming the project and who, by name; once its person confirms it in impartire it runs as them, every check again. Its person must manage the project. A deny removes read — and everything above it — on the project and everything under it, whatever else grants it, admins included (ADR 0047). A reason is required. Not yourself (422: you could not lift it); the subject must be the org's (422); already denied is 409. Audited: a project.access_denied event (its reason is not served by the audit log).

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • Idempotency-Keyheader · string

    Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request bodyDenyProjectAccessRequest
  • subject_type"member" | "team" | "role"required

    member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

  • subject_idstring (uuid)required

    The member's principal id, or the team's or role's id — of this org. Not yourself.

  • reasonstringrequired

    Why. Required: a deny is a reasoned, recorded act.

Response 201ProjectDeny

A deny: the subject loses read (and everything above it) on the project and everything under it, whatever else grants it.

  • projectobjectrequired

    The project.

    • idstring (uuid)required
    • namestringrequired
  • subjectobjectrequired
    • type"member" | "team" | "role"required

      member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

    • idstring (uuid)required

      The member's principal id, or the team's or role's id.

    • namestring or nullrequired

      The member's name, or the team's or role's. Null when it is no longer in the org.

  • reasonstringrequired
Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person cannot manage the project.
  • 404 not-found.
  • 409 conflict — already denied; confirmation-pending; or idempotency-in-flight.
  • 422 validation (a bad field, yourself, a subject not of the org), or idempotency-mismatch.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the permission service could not be reached; nothing changed.

DELETE/api/v1/projects/{id}/deny

Lift a deny on a project (guarded)

A guarded action (ADR 0081): it changes who can see the project. The app's own write runs, with its checks and words. **An API key's write happens at once.** **An OAuth token's does not**: 202 with a Confirmation naming the project and who, by name; once its person confirms it in impartire it runs as them, every check again. Its person must manage the project. The deny's record is kept, marked lifted. 404 when the subject has no active deny. Audited: a project.deny_lifted event.

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • subject_typequery · "member" | "team" | "role"required

    member: one person (GET /api/v1/members). team: everyone in the team. role: everyone holding the role. A team's or role's grant follows its membership.

  • subject_idquery · string (uuid)required

    The denied subject.

Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 204 An API key's lift: the deny no longer applies.
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person cannot manage the project.
  • 404 not-found.
  • 409 confirmation-pending.
  • 422 validation — a missing or bad subject_type or subject_id.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the deny is recorded as lifted but may still be enforced; deny again, then lift once the service is back.

POST/api/v1/projects/{id}/teams

Assign a team to a production (guarded)

A guarded action (ADR 0081): it changes who can see the project. The app's own write runs, with its checks and words. **An API key's write happens at once.** **An OAuth token's does not**: 202 with a Confirmation naming the project and who, by name; once its person confirms it in impartire it runs as them, every check again. Its person must administer the production (project administrate). The project must be a top-level project nobody owns and not itself a lane; the team the org's and not archived (422). The team's members read the production and get their own lane on it — a project the team owns, private to it. Idempotent: 201 when the lane was made, 200 when the team was already assigned. There is no unassign in the API (nor in the app). Audited: a project.team_bound event and the lane's capture.

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • Idempotency-Keyheader · string

    Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request bodyBindProjectTeamRequest
  • team_idstring (uuid)required

    A team of this org that is not archived.

Response 200ProductionLane

A team assigned to a production, and its lane.

  • productionobjectrequired

    The production (the project).

    • idstring (uuid)required
    • namestringrequired
  • teamobjectrequired
    • idstring (uuid)required
    • namestringrequired
  • laneobjectrequired

    The team's lane on the production: a project the team owns, private to it, attached to the production without inheriting its audience.

    • idstring (uuid)required
    • namestringrequired
  • createdbooleanrequired

    False when the team was already assigned (the lane is the existing one).

Response 201ProductionLane

A team assigned to a production, and its lane.

  • productionobjectrequired

    The production (the project).

    • idstring (uuid)required
    • namestringrequired
  • teamobjectrequired
    • idstring (uuid)required
    • namestringrequired
  • laneobjectrequired

    The team's lane on the production: a project the team owns, private to it, attached to the production without inheriting its audience.

    • idstring (uuid)required
    • namestringrequired
  • createdbooleanrequired

    False when the team was already assigned (the lane is the existing one).

Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person does not administer the production.
  • 404 not-found.
  • 409 confirmation-pending, or idempotency-in-flight.
  • 422 validation — team_id not a team of the org, an archived team, or a project that cannot be a production; idempotency-mismatch.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the permission service could not be reached; retry (assigning again is safe).

POST/api/v1/projects/{id}/move

Move a project under another, or to the top level (guarded)

A guarded action (ADR 0081): a project reads through its permission root, so moving it changes who can see it. The app's own move runs: Unfiled, the Library, a lane (nesting) and a team space (nesting) stay put (409); the parent must be a project of the org (422), not inside the moved subtree, allowed by the org's hierarchy rules and no more than five levels deep (422 invalid-hierarchy); and a move may narrow or keep the project's audience, never widen it (422 — widen a root from its settings page in the app). A move that narrows it revokes the public share links to the assets under it. Its person must be able to update the project and the new parent (no platform-admin bypass). **An API key's move happens at once**: 200 with the Project. **An OAuth token's does not**: 202 with a Confirmation saying where it goes and what that does; once its person confirms it in impartire it runs as them, every check again. Moving a project to where it already is answers 200 at once, for either credential. Audited: a project.moved event and the row's capture.

Scopes: access:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • Idempotency-Keyheader · string

    Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request bodyMoveProjectRequest
  • parent_idstring (uuid) or nullrequired

    The new parent project (GET /api/v1/projects), or null to make it a top-level project.

Response 200Project
  • idstring (uuid)required
  • namestringrequired
  • descriptionstring or nullrequired
  • parent_idstring (uuid) or nullrequired
  • visibilitystringrequired

    open | closed | private

  • project_typeobject or nullrequired

    The project's type (the org's project types: production, season, campaign…), or null if untyped.

    • idstring (uuid)required
    • namestringrequired
  • created_atstring (date-time)required
  • updated_atstring (date-time)required

    When its name, description or type last changed.

Response 202Confirmation

A guarded action an OAuth token asked for, waiting for its person to confirm it in impartire (ADR 0081). A guarded endpoint answers 202 with this and a Location; poll it until status is executed, declined or expired.

  • idstring (uuid)required
  • status"pending" | "confirmed" | "declined" | "expired" | "executed"required

    pending: waiting for the person to confirm or decline it in impartire (at confirm_url). confirmed: they confirmed and the action is running — poll again. executed: it ran; result holds its answer, or problem why it failed. declined: they said no; it will never run. expired: nobody decided within 15 minutes; it will never run (GET /api/v1/confirmations/{id} answers 410 confirmation-expired instead of this body; the person still sees it in impartire).

  • actionstringrequired

    The guarded action, e.g. run.signal.

  • resourceobjectrequired
    • typestringrequired

      The kind of resource the action is on, e.g. run.

    • idstring (uuid) or nullrequired
    • namestringrequired

      The resource as the person was shown it when the action was asked for.

  • summarystringrequired

    The action in words, as the person reads it on the confirmation page.

  • client_idstringrequired

    The OAuth client that asked.

  • confirm_urlstringrequired

    Where the person confirms or declines it. Show it to them; the API cannot confirm.

  • created_atstring (date-time)required
  • expires_atstring (date-time)required

    15 minutes after it was asked for. A pending confirmation past it is expired.

  • decided_atstring (date-time) or nullrequired

    When the person confirmed or declined it, or when it expired; null while pending.

  • resultanyrequired

    When executed and the action succeeded: the action's answer (what the endpoint would have returned with a key). Null otherwise.

  • problemProblem or nullrequired

    When executed and the action failed: the Problem it failed with. Null otherwise.

    • typestringrequired

      A stable URL naming the problem: https://impartire.com/problems/<code>. Branch on this.

    • titlestringrequired
    • statusintegerrequired
    • detailstringrequired

      What went wrong and what to do about it, written for the caller.

    • instancestringrequired

      The request path.

    • request_idstringrequired

      Also sent as the Request-Id header. Quote it when reporting a problem.

    • errorsarray of object

      On 422 validation: one entry per invalid field.

      • pathstringrequired

        The field or parameter, as a dotted path.

      • messagestringrequired
    • edit_seqinteger

      On 412 precondition-failed: the resource's current edit_seq.

    • etagstring

      On 412 precondition-failed for a project, a collection, a playlist or a schedule slot: its current ETag.

    • item_idstring

      On 409 already-member: the existing item's id (in the collection or playlist).

    • schema_versioninteger

      On 409 type-changed: the asset type's current schema_version.

    • confirmation_idstring

      On 409 confirmation-pending: the confirmation already waiting for its person (GET /api/v1/confirmations/{id}).

    • confirm_urlstring

      On 409 confirmation-pending: where the person confirms or declines it, in impartire.

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — the token's person cannot update the project or the new parent.
  • 404 not-found.
  • 409 conflict — an infrastructure project; confirmation-pending; or idempotency-in-flight.
  • 422 validation (parent_id not a project of the org, its own subtree, or a move that would widen who can see it), invalid-hierarchy, or idempotency-mismatch.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.
  • 503 authorization-unavailable — the permission service could not be reached; nothing changed.

GET/api/v1/projects/{id}/tags

List the tags on a project

A project's own tags: its sub-projects and assets do not inherit them. At most 500, ordered by the tag's normalized name; no cursor.

Scopes: projects:read

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

Response 200TagLinkList
  • dataarray of TagLinkrequired

    Ordered by the tag's normalized name. At most 500.

    • idstring (uuid)required

      The tag's id — what DELETE …/tags/{tag_id} and { id } on POST …/tags take.

    • namestringrequired

      The tag as first typed. Tags are matched by a normalized form: case, extra spaces and invisible characters are ignored.

    • scope"org" | "team"required

      org: the whole org's. team: private to one team (an OAuth token sees it only when its person is in the team or an org admin).

    • teamobject or nullrequired

      The owning team, for a team tag; null for an org tag.

      • idstring (uuid)required
      • namestringrequired
    • usage_countintegerrequired

      How many assets and projects carry the tag, across the org.

    • source"user" | "generated"required

      user: a person or an API credential added it. generated: applied from a generated summary.

    • added_atstring (date-time)required
  • next_cursorstring or nullrequired

    Always null: the list is returned whole (at most 500).

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope — the key lacks a required scope.
  • 404 not-found.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.

POST/api/v1/projects/{id}/tags

Add tags to a project

Each item is { name } — the org's tag of that name, created as an org tag when there is none — or { id } of an existing tag (the only way to add a team tag). A tag already on the project stays as it was, so the call is safe to repeat: no Idempotency-Key, no If-Match. Answers the project's whole tag list after. An OAuth token's person needs update on the project.

Scopes: projects:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

Request bodyAddTagsRequest
  • tagsarray of object or objectrequired

    1–50 tags, each { name } or { id }.

    • namestringrequired

      A tag name. The org's tag of that name is used, or created as an org tag if there is none.

Response 200TagLinkList
  • dataarray of TagLinkrequired

    Ordered by the tag's normalized name. At most 500.

    • idstring (uuid)required

      The tag's id — what DELETE …/tags/{tag_id} and { id } on POST …/tags take.

    • namestringrequired

      The tag as first typed. Tags are matched by a normalized form: case, extra spaces and invisible characters are ignored.

    • scope"org" | "team"required

      org: the whole org's. team: private to one team (an OAuth token sees it only when its person is in the team or an org admin).

    • teamobject or nullrequired

      The owning team, for a team tag; null for an org tag.

      • idstring (uuid)required
      • namestringrequired
    • usage_countintegerrequired

      How many assets and projects carry the tag, across the org.

    • source"user" | "generated"required

      user: a person or an API credential added it. generated: applied from a generated summary.

    • added_atstring (date-time)required
  • next_cursorstring or nullrequired

    Always null: the list is returned whole (at most 500).

Other responses
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — an OAuth token's person may see the project but lacks update on the project.
  • 404 not-found.
  • 422 validation (tags: 1–50 items, each { name } or { id }; a name that is empty or over 64 characters), or unknown-tag.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.

DELETE/api/v1/projects/{id}/tags/{tag_id}

Remove a tag from a project

Takes the tag off the project; the tag stays in the org's list. 404 when the project does not carry it, so a second DELETE is a 404.

Scopes: projects:write

Parameters
  • idpath · string (uuid)required

    The project's id, from GET /api/v1/projects.

  • tag_idpath · string (uuid)required

    The tag's id, from GET …/tags.

Other responses
  • 204 Removed.
  • 401 unauthenticated — no key, or an unknown, revoked or expired one.
  • 403 insufficient-scope, or insufficient-permission — an OAuth token's person lacks update on the project.
  • 404 not-found.
  • 429 rate-limited — the key's request budget is spent; wait Retry-After seconds.
  • 500 internal.