API reference
Introduction
The Veeton Studio API is a REST API over HTTPS with JSON bodies, organization-scoped machine keys, cursor pagination and one error envelope everywhere.
Resources are organised around what you hold and what you generate. Start with Products and Imports to get a catalogue in, Tasks to render, Exports to read everything back, and Webhooks to be told when things finish.
Within a major version only additive changes ship: new fields, new optional parameters, new values where a set is documented as open. Clients must ignore fields they do not know.
Base URL
https://api.veeton.com/v1Authentication
Every request carries an organization-scoped machine key as a bearer token. Mint one in the dashboard under Settings → API Keys. Keys start with ak_; dashboard session tokens are not accepted.
Keys carry scopes (products:read, tasks:write, …) and a request outside them is refused with 403 insufficient_scope. Verification is cached for about a minute, so revocation takes that long to apply. See the Authentication guide.
Authenticated request
curl https://api.veeton.com/v1/products \
-H "Authorization: Bearer $VEETON_KEY"Errors
Conventional HTTP status codes tell you the class of outcome; the body tells you what happened. Every error is the same envelope, { error: { type, code, message, param? } }. Switch on type for behaviour and on code for messaging; message is for people and is not stable.
Attributes
typeenumPossible enum values (9)
invalid_requestnot_foundunauthorizedforbiddenpayment_requiredconflictrate_limitedinternalnot_implemented
codestringmessagestringparamstring
HTTP status codes
200, 201, 202, 204The request worked.202means an asynchronous job was accepted.400The request was malformed or failed validation. Imports and tryon list every problem at once.401No key, or a key that is unknown, revoked or expired.402No active subscription or insufficient credits. Nothing was queued.403The key lacks a scope, or is bound to a user rather than an organization.404The resource does not exist in your organization.409A uniqueness conflict, such as areferencealready in use.413, 415The body is too large, or its content type is not accepted.422The request is well-formed but cannot be applied: an idempotency key reused with a different body, a subtype and inputs that do not match.429Rate limited. WaitRetry-Afterseconds and retry.5xxSomething failed on our side. Quote theX-Request-Idto support.
Error envelope
{
"error": {
"type": "invalid_request",
"code": "product_not_found",
"message": "Product 01HX...XY1 was not found.",
"param": "inputs.product_id"
}
}Pagination
Every list endpoint takes limit (1 to 100, default 25) and cursor, and returns the same envelope. Pass next_cursor back as cursor untilhas_more is false. Cursors are opaque and keyset-based, so rows added or deleted while you page are never skipped or repeated.
List envelope
{
"data": [ … ],
"next_cursor": "eyJpZCI6MTIzNDV9",
"has_more": true
}Idempotent requests
Send Idempotency-Key (any string up to 255 characters, a UUID by convention) on POST, PATCH and DELETE. The same key with the same request replays the stored response with Idempotent-Replayed: true; the same key with a different request is 422 idempotency_key_reused; a key still in flight is409 request_in_progress. Keys expire after 24 hours. A 5xx is never stored, so retrying it re-runs the request. See Idempotency.
Idempotent request
curl https://api.veeton.com/v1/tasks/beautifier \
-H "Authorization: Bearer $VEETON_KEY" \
-H "Idempotency-Key: 4d1b9f6e-6c2a-4c1e-9c3f-2a7e8b0d1f22" \
-H "Content-Type: application/json" \
-d @task.jsonRate limits
Per organization, per minute: 600 reads (GET) and 60 writes (POST, PATCH, DELETE). Every response carries the bucket's state inX-RateLimit-* headers. Past the limit you get 429 rate_limited with Retry-After; nothing was created and no idempotency key was consumed, so retrying is always safe.
Response headers
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 597
X-RateLimit-Reset: 1756910040Request ids
Every response carries X-Request-Id. Send your own value in that header (up to 128 characters of letters, digits, ., _, : and-) and it is echoed back, so one id follows a call through your logs and ours. Quote it when you contact support.
Response headers
X-Request-Id: req_7f3c2a1b9e4d4c0f8a6b