The REST API gives any script, build step or internal tool read access to your component library, design tokens and projects. It's the non-agent counterpart to the Agent Bridge: no MCP client needed, just an HTTP request.
Tip
The REST API is a Pro feature. Requests are unlimited on Pro and Lifetime.
Create a key
Open Settings → API Keys and click Create key. Give it a name that says
where it runs (CI pipeline, design-tokens script) so you know what you're
revoking later.
Copy the key immediately — it starts with xt_ and is shown once. Only a
hash is stored, so a lost key has to be replaced, not recovered.
Send it as a bearer token on every request:
curl https://www.xtractly.app/api/v1/components -H "Authorization: Bearer xt_your_key"Treat a key like a password: it has full read access to your library. Keep it in an environment variable, never in committed source or client-side code.
Endpoints
Every endpoint is read-only and returns JSON. A write goes through the Agent Bridge, not here.
| Endpoint | Returns |
|---|---|
GET /api/v1 | Which endpoints exist — also the cheapest way to check a key works. |
GET /api/v1/components | Your component library. |
GET /api/v1/components/:id | One component with its full file set. |
GET /api/v1/themes | Your design systems. |
GET /api/v1/themes/:id | A theme's tokens. |
GET /api/v1/projects | Your projects, most recently updated first. |
GET /api/v1/components
| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | — | Filter by title, case-insensitive substring |
limit | integer | 50 | Maximum results, capped at 100 |
GET /api/v1/components/:id
| Parameter | Type | Default | Description |
|---|---|---|---|
componentFormat | html | jsx | vue | svelte | as captured | Shape to return the component in |
styleFormat | inline | tailwind | as captured | How styling is carried |
The response names what it actually returned in servedAs, and carries a
notice when that differs from what was asked for — a component can only be
re-shaped from the markup captured with it, and jsx in particular is only
available for components captured as React. The
Agent Bridge docs explain the full matrix; it is
the same rule on both surfaces.
curl "https://www.xtractly.app/api/v1/components/COMPONENT_ID?componentFormat=vue" -H "Authorization: Bearer xt_your_key"GET /api/v1/themes/:id
| Parameter | Type | Default | Description |
|---|---|---|---|
variant | string | primary | Variant label to return, e.g. Dark |
format | css | — | Return a :root {} block as text/css instead of JSON |
GET /api/v1/themes and GET /api/v1/projects
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Maximum results, capped at 50 |
Tokens as CSS
?format=css on a theme returns a ready-to-paste :root block as text/css
instead of JSON — the usual way to pull tokens into a codebase:
curl "https://www.xtractly.app/api/v1/themes/THEME_ID?format=css" -H "Authorization: Bearer xt_your_key" > tokens.cssResponses
Successful responses wrap the payload in data, with count on list
endpoints:
{
"data": [
{
"id": "k17...",
"title": "Pricing card",
"projectName": "Marketing site",
"createdAt": "2026-09-22T10:14:00.000Z"
}
],
"count": 1
}
Errors return an HTTP status plus a machine-readable error and a readable
message. Every failure has this shape, including a wrong URL or a wrong
method — you never get an HTML page back from /api/v1.
| Status | error | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_component_format | componentFormat isn't one of the four. | Use html, jsx, vue or svelte. |
| 400 | invalid_style_format | styleFormat isn't inline or tailwind. | Use one of those. |
| 401 | missing_api_key | No Authorization: Bearer header. | Send the key. The response carries WWW-Authenticate: Bearer. |
| 401 | invalid_api_key | The key is wrong or was revoked. Also what you get for an xtr_ Agent Bridge token — the two are separate credentials. | Create a key in Settings → API Keys. |
| 403 | pro_required | Your plan doesn't include API access. | Upgrade, or use the extension and app as normal. |
| 404 | not_found | No such component or theme in your library. Another account's id reads as one that doesn't exist. | Check the id against a list endpoint. |
| 404 | variant_not_found | The theme has no variant with that label. | Omit variant, or read the theme's variants list first. |
| 404 | unknown_endpoint | No such path under /api/v1. | GET /api/v1 lists the real ones. |
| 405 | method_not_allowed | You sent a write to a read-only endpoint. | Writes go through the Agent Bridge. |
| 503 | service_unavailable | The key couldn't be verified right now — our problem, not your key's. | Retry after the Retry-After interval. Don't rotate the key. |
Tracking usage
Every request is counted twice, both visible in Settings:
- Per key — each key in Settings → API Keys shows its lifetime request count and when it was last used. A key that hasn't been used in months is usually one to revoke.
- Per account — Settings → Usage shows requests in the current rolling 30-day window.
Counting happens after the key is verified, so failed authentication attempts never touch your numbers. A request to a path that doesn't exist isn't counted either — it never reached an endpoint.