Uploads take two calls, so file bytes never pass through the API. Both need the brands:files scope, and the token’s creator must be an owner or admin of the workspace named in X-Workspace-Key.
1. Start the upload
POST /brands/{brand}/files with the place the file is for.
curl -X POST -H "Authorization: Bearer $TARKLE_TOKEN" -H "X-Workspace-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{"slot": "icon", "size": 18204, "filename": "icon.png"}' \
https://tarkle.com/api/v1/brands/acme-bank/filesslot |
What it does |
|---|---|
icon, main_logo, banner, social_image, favicon |
Replaces the brand’s current one. |
logo |
Adds an extra logo. |
asset |
Adds a file to a collection. |
size and filename are optional. They let a file that is too large or the wrong type be refused before you upload it.
The answer (201) holds:
file_id, which you use in step 3. It only works for this brand and this place.upload.urlandupload.method(PUT). The address expires afterupload.expires_inseconds (3,600).max_bytesandextensions(the allowed file types, ornullfor any type).complete_url.
2. Send the file
PUT the file bytes to upload.url. Send the bytes as the body, with no extra authorization header.
curl -X PUT --data-binary @icon.png "$UPLOAD_URL"3. Complete the upload
POST /brands/{brand}/files/{file_id}/complete. Tarkle checks what was stored and attaches it.
curl -X POST -H "Authorization: Bearer $TARKLE_TOKEN" -H "X-Workspace-Key: $KEY" \
https://tarkle.com/api/v1/brands/acme-bank/files/$FILE_ID/completeThe checks are the ones of the brand editor: the file’s real type (its first bytes, not its name), its size and that it arrived.
| Place | Types | Largest |
|---|---|---|
icon, main_logo, logo |
PNG, JPG, WebP, SVG | 10 MB |
banner, social_image |
PNG, JPG, WebP | 10 MB |
favicon |
PNG, JPG, WebP, SVG, ICO | 2 MB |
asset |
Any | 100 MB |
For logo, the body may hold name, type (primary, secondary, monochrome, reversed, icon, favicon, square or social media) and usage (digital, print or all purpose). For asset, send collection_id, or collection_name to start a new collection, plus an optional name and type. The other places take no body.
The answer (200) holds slot, file_id, size and already_attached. Completing the same file again answers the same with already_attached: true and changes nothing. A replaced icon, logo, banner, social image or favicon is removed from storage unless the brand still uses it.
Errors
| Answer | Meaning |
|---|---|
400 invalid_request |
The body, the slot or the file_id is wrong, or the file_id was made for another brand or place. |
409 file_not_uploaded |
Nothing was found at the upload address. PUT the file, then complete again. |
413 file_too_large |
The declared size is over the limit for that place. |
422 invalid_file |
The stored file is too large, empty or not a real file of an allowed type. The file is removed. |
409 conflict |
A brand holds 20 extra logos, 30 collections or 200 files in a collection. Or the brand still has images from the older editor, which blocks asset uploads: open the brand in the app once to move them into collections. |
An upload is recorded in the Activity as brand.updated with the place, and brand.updated webhooks fire once.
The API does not remove files, and it does not upload team photos, guideline images or fonts.