---
title: "Developer documentation"
description: "The 0layers public REST API: authentication, endpoints, rate limits, error codes, and the standard sequence for turning a website into generated social content."
canonical: "https://0layers.com/developers"
source: "https://0layers.com/developers"
---

# Developer documentation

> The 0layers public REST API: authentication, endpoints, rate limits, error codes, and the standard sequence for turning a website into generated social content.

## Developer documentation

The 0layers public REST API turns a business website into on-brand social content. Version 1.0.0. The machine-readable description of everything below is at [/openapi.json](https://0layers.com/openapi.json).

### Base URL and authentication

Every request needs an API key, sent as a bearer token. Create one at `/settings/api-keys` while signed in. Keys start with `0l_live_` and are shown once at creation — store it then, because it cannot be read back.

Base URL: https://flexible-sandpiper-126.convex.site/api/v1
Authorization: Bearer 0l\_live\_…

Keys are created, listed, and revoked on that one screen, reachable from the account menu. There is no OAuth flow and no client registration endpoint; an agent acting for a user needs that user to paste in a key. See [the authentication guide](https://0layers.com/auth) for the full walkthrough.

### The standard sequence

Extraction and generation are asynchronous. Both return `202` and are polled through a matching read endpoint.

1.  `POST /brands` with the business website URL.
2.  `POST /brands/{brandId}/extract` to learn the brand.
3.  `GET /brands/{brandId}/extract` until status is complete.
4.  `POST /brands/{brandId}/generate` to start a batch. This spends credits.
5.  `GET /brands/{brandId}/generations` for finished content.

curl -sS "https://flexible-sandpiper-126.convex.site/api/v1/brands" \\
  -X POST \\
  -H "Authorization: Bearer $API\_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{"sourceUrl":"https://example.com"}'

### Endpoints

Method

Path

What it does

GET

/brands

List brands

POST

/brands

Create a brand from a website

GET

/brands/{brandId}

Read one brand

PATCH

/brands/{brandId}

Update brand settings

DELETE

/brands/{brandId}

Delete a brand

GET

/brands/{brandId}/extract

Poll extraction status

POST

/brands/{brandId}/extract

Start brand extraction

POST

/brands/{brandId}/generate

Start a generation batch

GET

/brands/{brandId}/generations

List completed generations

GET

/generations/{generationId}

Read one generation

GET

/billing/credits

Read the credit balance

### Response shapes

Successful reads return a `data` envelope. Lists add a `pagination` block with an opaque cursor. Errors return a stable machine-readable `code` alongside a human message; branch on the code, not the message.

{ "data": { … } }

{ "data": \[ … \], "pagination": { "hasMore": true, "nextCursor": "…" } }

{ "error": { "code": "RATE\_LIMIT\_EXCEEDED", "message": "…" } }

### Rate limits

Limits are per API key, not per user. Exceeding one returns `429` with code `RATE_LIMIT_EXCEEDED` and a `Retry-After` header in seconds.

Every response carries a `RateLimit-Policy` header stating these limits, so a client can pace itself before it ever sees a 429. There is no live `RateLimit-Remaining`: the limiter reports whether a request was allowed, not how much budget is left, and a remaining count we cannot measure would be a number you would throttle against wrongly.

-   `read` — GET endpoints: **60 requests/minute, burst 20**
-   `write` — Create, update, delete, and extraction triggers: **20 requests/minute, burst 5**
-   `generate` — Generation triggers: **5 requests/hour**

### Errors

Status

Meaning

What to do

401

API key missing, malformed, invalid, or revoked.

Issue a new key from the dashboard. Do not retry.

402

Insufficient credits for the requested generation.

Top up credits, then retry.

404

Brand or generation does not exist, or is not owned by this key's user.

Do not retry with the same identifier.

409

Extraction is already in progress for this brand.

Poll the extraction status endpoint instead of starting another.

422

Validation failed, or the resource is in the wrong state.

Fix the request. Retrying unchanged will fail the same way.

429

Rate limit exceeded for this key.

Back off until the bucket refills or the window rolls over.

### Versioning

The version is in the path (`/api/v1`). Additive changes — new endpoints, new response fields, new error codes — ship within `v1`. Anything that would break an existing integration ships as a new path version instead. Treat unknown response fields as forward compatibility, not as an error.

**Deprecation.** An endpoint that is going away is announced on the responses you are already making: a `Deprecation` header (RFC 9745) marks it, and a `Sunset` header (RFC 8594) carries the date it stops working. Both appear at least **90 days** before removal, so an integration finds out by running rather than by reading a changelog.

### Discovery documents

Everything an agent needs to find and use 0layers without a human in the loop:

-   [/openapi.json](https://0layers.com/openapi.json) — OpenAPI 3.1 description of this API
-   [/.well-known/ai-catalog.json](https://0layers.com/.well-known/ai-catalog.json) — Agentic Resource Discovery catalog
-   [/.well-known/agent-skills/index.json](https://0layers.com/.well-known/agent-skills/index.json) — what 0layers can do, as skills
-   [/.well-known/agent-card.json](https://0layers.com/.well-known/agent-card.json) — A2A agent card
-   [/.well-known/api-catalog](https://0layers.com/.well-known/api-catalog) — RFC 9727 API catalog
-   [/llms.txt](https://0layers.com/llms.txt) — what 0layers is and when to reach for it

Every page on this site also serves Markdown: send `Accept: text/markdown` or append `.md` to the path.

### Support

Integration questions, rate-limit increases, and bug reports go to [hello@0layers.com](mailto:hello@0layers.com). Include the endpoint, the error code, and roughly when the request was made.
