Skip to content
VectorFast Render docs

REST API reference

Every VectorFast Render /v1 endpoint with its parameters, request body, response fields, and status codes, generated from the OpenAPI 3.1 document.

VectorFast Render API 0.1.0. Base URL: https://vectorfast.ai. The machine-readable document is GET /v1/openapi.json.

Authenticate every /v1 call except this document with an API key created in your account: Authorization: Bearer vf_live_….

Each key is limited to 60 requests per 60 seconds. Errors always have the shape {"error": {"code", "message", "docs"}}.

Billing is not connected yet: credits_charged is always 0 and GET /v1/usage reports credits_remaining: null.

Templates: launch-post, blog-post, social-square, achievement-card, invite-card, stat-card, changelog, quote-card. GET /v1/templates/{id} returns each one's params schema, examples and an agent_example (a prompt and the render call it should become). A template listed with status: "planned" cannot be rendered yet.

Endpoints

MethodPathSummary
GET/v1/templatesList templates
GET/v1/templates/{id}Describe a template
POST/v1/rendersRender an image
POST/v1/previewsRender a watermarked preview
GET/v1/usageUsage for the current period
GET/v1/brand-kitsList brand kits
POST/v1/brand-kitsCreate a brand kit
GET/v1/brand-kits/{id}Read a brand kit
PUT/v1/brand-kits/{id}Update a brand kit
DELETE/v1/brand-kits/{id}Delete a brand kit
POST/v1/brand-kits/{id}/logoUpload a logo
GET/v1/openapi.jsonThis document

Templates

Official templates, their param schemas and preview images.

List templates

GET /v1/templates

All catalog templates. preview_url is a signed /i/ URL of the English example at the default size.

Auth: Authorization: Bearer <API key>.

Response 200

FieldTypeRequiredConstraintsDescription
templatesTemplateListing[]yes——

Status codes

StatusMeaning
200The catalog.
401Missing, malformed, unknown or revoked API key (unauthorized).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Describe a template

GET /v1/templates/{id}

Params JSON Schema (draft 2020-12, generated from the template's zod schema), sizes, examples and an agent prompt.

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
idpath"launch-post" | "blog-post" | "social-square" | "achievement-card" | "invite-card" | "stat-card" | "changelog" | "quote-card"yes—

Response 200 (TemplateDescription)

The template. Content types: application/json.

Status codes

StatusMeaning
200The template.
401Missing, malformed, unknown or revoked API key (unauthorized).
404The id is not in the catalog (template_not_found).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Renders

Synchronous renders and watermarked previews.

Render an image

POST /v1/renders

Validates the template, params, format and size, then answers from the edge cache, the R2 cache or a fresh render (cached tells which).

Send Idempotency-Key to make retries safe: the same key with the same body returns the stored JSON for 24 hours (header Idempotent-Replayed: true); the same key with a different body answers 409 invalid_params.

Every call records one usage row (template, format, cached); params are never stored.

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
Idempotency-KeyheaderstringnoClient-chosen retry key, printable ASCII without spaces.

Request body (application/json)

FieldTypeRequiredConstraintsDescription
templatestringyespattern ^([a-z0-9-]{1,64})(?:@(\d{1,3}))?$—
format"png" | "jpeg" | "webp"nodefault "png"—
widthintegerno16–4096—
heightintegerno16–4096—
scale1 or 2nodefault 1—
brand_kitstringno1–64 chars—
paramsobjectyes——
response"url" | "binary"nodefault "url"—

Body of POST /v1/renders and POST /v1/previews. params must satisfy the template's own schema (see GET /v1/templates/{id} → params_schema, or the TemplateParams_* components).

Response 200 (RenderResponse)

FieldTypeRequiredConstraintsDescription
idstringyespattern ^rnd_[0-9a-f]{32}$Render id; stable across idempotent replays.
urlstring (uri)yes—Signed /i/{template}.{format} URL serving the same pixels. It never expires.
cache_keystringyespattern ^[0-9a-f]{64}$—
cachedbooleanyes—True when a cache layer answered and nothing was rendered.
credits_charged0yes—Always 0 in this phase: credits are connected in a later release. Cache hits will stay 0.
widthintegeryes——
heightintegeryes——
scale1 | 2yes——
format"png" | "jpeg" | "webp"yes——
render_msnumberyes—Renderer time (layout + raster + encode) for this request; 0 on cache hits.
template_versionstringyes—<id>@<semver> of the template that produced the pixels.
watermarktrueno—Present only on /v1/previews responses.

Status codes

StatusMeaning
200The render. With response: "url" a JSON body; with response: "binary" the image bytes and the same facts in headers.
400Invalid request body, params, size or Idempotency-Key (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
404Unknown or planned template, or unknown brand kit (template_not_found, brand_kit_not_found).
409Idempotency-Key reused with a different body (invalid_params).
413Body larger than 256 KiB (invalid_params).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
500The renderer failed (render_failed).
502Fonts could not be loaded (render_failed).
503The API is not configured or a dependency is down (render_unavailable).

Render a watermarked preview

POST /v1/previews

Same body and validation as /v1/renders; the image carries a translucent PREVIEW label, is cached at the edge only (never in R2), charges nothing and records no usage. Idempotency-Key is ignored.

Auth: Authorization: Bearer <API key>.

Request body (application/json)

FieldTypeRequiredConstraintsDescription
templatestringyespattern ^([a-z0-9-]{1,64})(?:@(\d{1,3}))?$—
format"png" | "jpeg" | "webp"nodefault "png"—
widthintegerno16–4096—
heightintegerno16–4096—
scale1 or 2nodefault 1—
brand_kitstringno1–64 chars—
paramsobjectyes——
response"url" | "binary"nodefault "url"—

Body of POST /v1/renders and POST /v1/previews. params must satisfy the template's own schema (see GET /v1/templates/{id} → params_schema, or the TemplateParams_* components).

Response 200 (RenderResponse)

FieldTypeRequiredConstraintsDescription
idstringyespattern ^rnd_[0-9a-f]{32}$Render id; stable across idempotent replays.
urlstring (uri)yes—Signed /i/{template}.{format} URL serving the same pixels. It never expires.
cache_keystringyespattern ^[0-9a-f]{64}$—
cachedbooleanyes—True when a cache layer answered and nothing was rendered.
credits_charged0yes—Always 0 in this phase: credits are connected in a later release. Cache hits will stay 0.
widthintegeryes——
heightintegeryes——
scale1 | 2yes——
format"png" | "jpeg" | "webp"yes——
render_msnumberyes—Renderer time (layout + raster + encode) for this request; 0 on cache hits.
template_versionstringyes—<id>@<semver> of the template that produced the pixels.
watermarktrueno—Present only on /v1/previews responses.

Status codes

StatusMeaning
200The preview; watermark: true in JSON responses.
400Invalid request body, params, size or Idempotency-Key (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
404Unknown or planned template, or unknown brand kit (template_not_found, brand_kit_not_found).
413Body larger than 256 KiB (invalid_params).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
500The renderer failed (render_failed).
503The API is not configured or a dependency is down (render_unavailable).

Brand kits

Versioned brand kits: colors, fonts and a logo that templates render with.

List brand kits

GET /v1/brand-kits

Your kits at their current version, oldest first (the first is the default for renders). With no kits of your own the list holds the read-only built-in default kit. limit is how many kits your plan includes.

Auth: Authorization: Bearer <API key>.

Response 200

FieldTypeRequiredConstraintsDescription
brand_kitsBrandKit[]yes——
limitintegeryes——

Status codes

StatusMeaning
200The kits.
401Missing, malformed, unknown or revoked API key (unauthorized).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Create a brand kit

POST /v1/brand-kits

Creates version 1. Colors and fonts you leave out start from the built-in kit. Font families must be Google Fonts families that load at weights 400 and 700; custom font uploads are not available yet.

Auth: Authorization: Bearer <API key>.

Request body (application/json)

FieldTypeRequiredConstraintsDescription
namestringyes1–64 chars—
colorsobjectno——
colors.backgroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.foregroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.mutedstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentForegroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.surfacestringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
fontsobjectno——
fonts.headingobjectno——
fonts.bodyobjectno——

Response 201 (BrandKit)

FieldTypeRequiredConstraintsDescription
idstringyes—bk_ + 16 base32 characters, or default for the built-in kit.
namestringyes——
versionstringyes—<id>@<n>. Every save creates a new version; renders fold it into the cache key, so old images are never served for a changed kit.
version_numberintegeryes1–∞—
is_defaultbooleanyes—The kit renders use when brand_kit is omitted: your oldest kit, or the built-in kit when you have none.
read_onlybooleanyes—True only for the built-in default kit.
colorsobjectyes——
colors.backgroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.foregroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.mutedstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentForegroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.surfacestringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
fontsobjectyes——
fonts.headingobjectyes——
fonts.bodyobjectyes——
logoobject or nullyes—Set by POST /v1/brand-kits/{id}/logo. URLs are signed, immutable and never expire.
logo.svg_urlstring or null (uri)yes——
logo.png_urlstring or null (uri)yes——
logo.source_format"png" | "jpeg" | "svg"yes——
logo.widthintegeryes——
logo.heightintegeryes——
logo.png_widthintegeryes—Twice width (capped at 4096).
logo.png_heightintegeryes——
logo.path_countintegeryes——
created_atstring or null (date-time)yes——
updated_atstring or null (date-time)yes——

Status codes

StatusMeaning
201The new kit.
400Invalid request body, params, size or Idempotency-Key (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
403Your plan's brand-kit limit is reached (brand_kit_limit_reached).
413Body larger than 256 KiB (invalid_params).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Read a brand kit

GET /v1/brand-kits/{id}

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
idpathstringyesBrand kit id. GET also accepts a pinned version such as bk_…@2 and the built-in default.

Response 200 (BrandKit)

FieldTypeRequiredConstraintsDescription
idstringyes—bk_ + 16 base32 characters, or default for the built-in kit.
namestringyes——
versionstringyes—<id>@<n>. Every save creates a new version; renders fold it into the cache key, so old images are never served for a changed kit.
version_numberintegeryes1–∞—
is_defaultbooleanyes—The kit renders use when brand_kit is omitted: your oldest kit, or the built-in kit when you have none.
read_onlybooleanyes—True only for the built-in default kit.
colorsobjectyes——
colors.backgroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.foregroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.mutedstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentForegroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.surfacestringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
fontsobjectyes——
fonts.headingobjectyes——
fonts.bodyobjectyes——
logoobject or nullyes—Set by POST /v1/brand-kits/{id}/logo. URLs are signed, immutable and never expire.
logo.svg_urlstring or null (uri)yes——
logo.png_urlstring or null (uri)yes——
logo.source_format"png" | "jpeg" | "svg"yes——
logo.widthintegeryes——
logo.heightintegeryes——
logo.png_widthintegeryes—Twice width (capped at 4096).
logo.png_heightintegeryes——
logo.path_countintegeryes——
created_atstring or null (date-time)yes——
updated_atstring or null (date-time)yes——

Status codes

StatusMeaning
200The kit at its current (or pinned) version.
401Missing, malformed, unknown or revoked API key (unauthorized).
404No such kit or version on your account (brand_kit_not_found).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Update a brand kit

PUT /v1/brand-kits/{id}

Saves a new version. Fields you leave out keep their current values; the logo only changes through POST /v1/brand-kits/{id}/logo. Earlier versions stay readable and renderable when pinned.

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
idpathstringyesBrand kit id. GET also accepts a pinned version such as bk_…@2 and the built-in default.

Request body (application/json)

FieldTypeRequiredConstraintsDescription
namestringno1–64 chars—
colorsobjectno——
colors.backgroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.foregroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.mutedstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentForegroundstringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.surfacestringnopattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
fontsobjectno——
fonts.headingobjectno——
fonts.bodyobjectno——

Response 200 (BrandKit)

FieldTypeRequiredConstraintsDescription
idstringyes—bk_ + 16 base32 characters, or default for the built-in kit.
namestringyes——
versionstringyes—<id>@<n>. Every save creates a new version; renders fold it into the cache key, so old images are never served for a changed kit.
version_numberintegeryes1–∞—
is_defaultbooleanyes—The kit renders use when brand_kit is omitted: your oldest kit, or the built-in kit when you have none.
read_onlybooleanyes—True only for the built-in default kit.
colorsobjectyes——
colors.backgroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.foregroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.mutedstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.accentForegroundstringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
colors.surfacestringyespattern ^#(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$—
fontsobjectyes——
fonts.headingobjectyes——
fonts.bodyobjectyes——
logoobject or nullyes—Set by POST /v1/brand-kits/{id}/logo. URLs are signed, immutable and never expire.
logo.svg_urlstring or null (uri)yes——
logo.png_urlstring or null (uri)yes——
logo.source_format"png" | "jpeg" | "svg"yes——
logo.widthintegeryes——
logo.heightintegeryes——
logo.png_widthintegeryes—Twice width (capped at 4096).
logo.png_heightintegeryes——
logo.path_countintegeryes——
created_atstring or null (date-time)yes——
updated_atstring or null (date-time)yes——

Status codes

StatusMeaning
200The kit at its new version.
400Invalid body, or the read-only built-in kit (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
404No such kit on your account (brand_kit_not_found).
409The kit changed while the request ran (brand_kit_conflict); read it and retry.
413Body larger than 256 KiB (invalid_params).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Delete a brand kit

DELETE /v1/brand-kits/{id}

Soft delete: the kit stops counting toward your limit, renders that name it answer 404, and its signed image URLs stop rendering on a cache miss.

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
idpathstringyesBrand kit id. GET also accepts a pinned version such as bk_…@2 and the built-in default.

Response 200

FieldTypeRequiredConstraintsDescription
idstringyes——
deletedtrueyes——

Status codes

StatusMeaning
200Deleted.
400The read-only built-in kit (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
404No such kit on your account (brand_kit_not_found).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

POST /v1/brand-kits/{id}/logo

Send the file as the raw body with Content-Type: image/png, image/jpeg or image/svg+xml, or as multipart/form-data with a part named file. At most 5 MB and 4096×4096 pixels; the file name is ignored and never stored.

PNG and JPEG logos are traced to SVG with the same engine as the free VectorFast vectorizer, then cleaned (tiny fragments, near-duplicate colors, coordinate precision); the untouched trace is kept too. SVG logos skip tracing and are sanitized (scripts, event handlers, external links and embedded HTML are removed). Both get a 2x PNG. Tracing is a best-effort candidate, not an exact reconstruction of the original artwork.

Saves a new kit version; renders and signed URLs that name the kit use it from then on. Limited to 3 uploads a minute and 10 an hour per API key.

Auth: Authorization: Bearer <API key>.

Parameters

NameInTypeRequiredDescription
idpathstringyesBrand kit id. GET also accepts a pinned version such as bk_…@2 and the built-in default.

Request body (image/png, image/jpeg, image/svg+xml, multipart/form-data)

FieldTypeRequiredConstraintsDescription
filestring (binary)yes——

Response 200

FieldTypeRequiredConstraintsDescription
brand_kitBrandKityes——
versionstringyes——
logoBrandKit/properties/logoyes——

Status codes

StatusMeaning
200The kit at the version that carries the logo.
400Over 5 MB or 4096×4096, a body that does not match its Content-Type, an unreadable image, or the read-only built-in kit (invalid_params).
401Missing, malformed, unknown or revoked API key (unauthorized).
404No such kit on your account (brand_kit_not_found).
409The kit changed while the upload ran (brand_kit_conflict); upload again.
415Content-Type is not PNG, JPEG, SVG or multipart (invalid_params).
429More than 3 uploads a minute or 10 an hour for this API key (rate_limited); honour Retry-After.
500The pipeline or storage failed (render_failed).
503The API is not configured or a dependency is down (render_unavailable).

Account

Usage for the current API key's account.

Usage for the current period

GET /v1/usage

Renders counted in the current UTC calendar month for the key's account. credits_charged is 0 and credits_remaining is null until billing is connected, after which the period follows the subscription.

Auth: Authorization: Bearer <API key>.

Response 200 (Usage)

FieldTypeRequiredConstraintsDescription
periodobjectyes——
period.startstring (date-time)yes——
period.endstring (date-time)yes——
rendersintegeryes—POST /v1/renders calls in the period, cache hits included.
cached_rendersintegeryes——
credits_charged0yes—Always 0 until billing is connected.
credits_remaininginteger or nullyes—null until billing is connected.

Status codes

StatusMeaning
200Usage.
401Missing, malformed, unknown or revoked API key (unauthorized).
429More than 60 requests in 60 seconds for this API key (rate_limited); honour Retry-After.
503The API is not configured or a dependency is down (render_unavailable).

Meta

This document.

This document

GET /v1/openapi.json

Auth: none.

Response 200

The OpenAPI 3.1 document. Content types: application/json.

Status codes

StatusMeaning
200The OpenAPI 3.1 document.

Errors

Every error body has the same shape; see Errors for what each code means and how to fix it.

FieldTypeRequiredConstraintsDescription
errorobjectyes——
error.code"invalid_params" | "unauthorized" | "insufficient_credits" | "template_not_found" | "brand_kit_not_found" | "brand_kit_limit_reached" | "brand_kit_conflict" | "not_found" | "rate_limited" | "render_failed" | "render_timeout" | "render_unavailable"yes——
error.messagestringyes—Public-safe; names a field or rule, never echoes a value.
error.docsstring (uri)yes——

Updated 2026-10-30 · Markdown version