Uploading a file
Two calls: reserve a slot, then send the bytes.1
Reserve the slot
uploadId, the slot’s state and an expiresAt.2
Send the bytes
Asset, including its assetId and publicUrl.The server verifies the actual file bytes against the
contentType and sizeBytes you declared. Declaring one thing and sending another fails.Limits
A slot moves through
INITIATED → UPLOADING → CLEANING → COMPLETED, or ends in FAILED / EXPIRED.
Generating creative
Image generation is asynchronous: submit, poll, attach.status moves PENDING → GENERATING → SUCCEEDED or FAILED. On success the response carries a contentUrl; on failure, an error.
Not happy with it? POST /api/v1/image-generations/{requestId}/regenerate runs it again from the same request.
aspectRatio is SQUARE or PORTRAIT.
destinationUrl here is a hint about who you are and nothing more: only the scheme, host and path reach the image model, never the query string. A URL still carrying a placeholder after the query string is cut is left out of the prompt altogether — the image is generated before the campaign exists, so there is no campaign to name.Attaching creative to a campaign
Pass asset ids inmediaAssetIds when you create the campaign. Assets carry a source of USER_UPLOAD or AI_GENERATED, so you can tell later which is which.
DELETE /api/v1/assets/{assetId} removes one.