Finish upload
finish_uploadStep 2 of 2: turn bytes you have already sent to storage into a Playbook asset. Call it only after every step returned by create_upload_url has succeeded — this call does not transfer anything, it records what landed. Pass the signed_gcs_id from create_upload_url unchanged. If a step failed, do NOT call this; start over with a fresh create_upload_url.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Byte size, as passed to create_upload_url | |
| title | No | Asset title. Pass the same filename you gave create_upload_url — it is NOT remembered between the two calls, and omitting it creates an untitled asset. | |
| width | No | Pixel width, if known. Do not guess. | |
| height | No | Pixel height, if known. Do not guess. | |
| media_type | Yes | MIME type of the stored file. Required, and it must be the SAME value you gave when you asked for the upload address — nothing is carried between the two calls, so a different value here labels the asset as something the stored bytes are not. | |
| description | No | Optional description | |
| ai_generated | No | Mark the asset as produced by an AI tool. On this upload path the flag does more than label it: it also suppresses automatic duplicate merging and grouping, which matters when you are pushing many variants of one image. It only has that effect when set HERE, at creation — setting it later records the marker but cannot un-merge anything. | |
| organization | No | Workspace slug, as returned by list_organizations. Omit it when the account has a single workspace — it is then resolved from your token. Pass it only when the account has several, or when you mean a workspace other than the obvious one. | |
| signed_gcs_id | Yes | The value create_upload_url returned. Pass it back exactly, it is signed. | |
| ai_agent_payload | No | Free-form JSON metadata stored with the asset — for example generation settings such as model and seed, or a source job id. Playbook never interprets it. Max 4096 BYTES of serialised JSON; anything larger is REJECTED, never truncated. A write REPLACES the whole object. Readable per asset (get_asset, or list/search with get_ai_payload=true) but NOT searchable or filterable. | |
| collection_token | No | Destination board token. If omitted or unknown, Playbook silently routes to a default anonymous board — call get_board first to validate. |