API reference

A distilled map of the /v1 surface. The complete machine-readable reference — request/response examples for every endpoint, the wall JSON contract, and the Stripe click-path — is a single request away at /llms-full.txt (agents fetch it automatically from /llms.txt).

Authentication

Private endpoints take the API key as a bearer token:

Authorization: Bearer lsk_live_<keyid>_<secret>

The key is returned exactly once, by POST /v1/verify (see the quickstart). Store it in an environment variable; never commit it. Public endpoints (wall JSON, the demo wall, /logo/, /health) need no auth.

Endpoints

MethodPathAuthWhat it does
POST/v1/signupRequest a verification code. Always 202, identical body (no account enumeration).
POST/v1/verifyExchange the emailed 8-char code for the API key — shown exactly once.
GET/v1/meAPI keyAccount state, plan, scopes, limits, and publish_blockers[].
POST/v1/stripe/connectAPI keyConnect via read-only restricted key. Direct HTTPS only — never MCP. Rejects sk_ keys.
POST/v1/stripe/confirmAPI keyPublish authorization — the code from the connected Stripe account's own inbox.
POST/v1/stripe/connect_urlAPI keyOne-time OAuth URL (15 min). A human must open it; OAuth skips the confirm step.
GET/v1/stripe/connectionAPI keyConnection mode, status (active/degraded/revoked), livemode, last sync, cursor age.
GET/v1/wallsAPI keyList walls; each carries published: true|false plus a reason when false.
POST/v1/wallsAPI keyCreate a wall. Accepts Idempotency-Key.
GET/v1/walls/:public_idPublic wall JSON. Bare 404 until publishable. Paginated (limit 60, cursor).
GET/v1/walls/demoPublic demo wall — same shape, no signup. Integrate against this first.
POST/v1/domainsAPI keyManually add a domain. Accepts Idempotency-Key.
POST/v1/exclusionsAPI keyExclude a domain from all walls — applies at serve time, never waits on a sync.
DELETE/v1/exclusions/:domainAPI keyRemove an exclusion (works on every plan).
GET/v1/sync/statusAPI keySync funnel counts; poll latest_job.state after connecting.
POST/v1/sync/refreshAPI keyOn-demand sync, 1/hour/connection (scheduled sync runs daily).
POST/v1/billing/checkout_urlAPI keyStripe Checkout URL for Pro — a human opens it and pays.
POST/v1/billing/portal_urlAPI keyStripe Billing Portal URL for accounts that have paid before.
POST/v1/unpublish_allAPI keyPanic button: every wall 404s immediately, hard cache purge.
POST/v1/republishAPI key (admin)Clear the panic button (deliberately harder than unpublishing).
GET/healthService health: db / stripe / logodev checks.
GET/logo/:domain.pngLogo asset route (redirects to the CDN); what wall JSON logo paths point at.

Error envelope

Every non-2xx response, everywhere, uses one shape:

{ "error": { "code": "machine_readable", "message": "human readable" } }

One deliberate exception: GET /v1/walls/:public_id returns a bare 404 (no body detail) while a wall isn’t publishable — existence is not leaked. Use the authed GET /v1/walls to see published plus a reason instead of debugging the 404 (why it works this way: security).

Idempotency

POST /v1/walls and POST /v1/domains accept an Idempotency-Key header (any unique string). Retries with the same key return the original result with "idempotent_replay": true. POST /v1/signup needs none — it always returns the identical 202 and mints nothing until verify.

Rate limits

EndpointLimit
POST /v1/signup3 codes/hour, 10/day per email; per-IP limits apply
POST /v1/verify15 lifetime failed codes per account, then verification locks 24h
POST /v1/stripe/confirmSame budget construction as /v1/verify
POST /v1/billing/checkout_url5/hour per account
POST /v1/sync/refresh1/hour per connection (scheduled sync also runs daily)
GET /v1/walls/:public_idCached: s-maxage=60, stale-while-revalidate=300
Other authed /v1 endpointsGenerous; back off on 429 and honor Retry-After

MCP

A Streamable HTTP MCP server lives at https://logosyncer.com/mcp (bearer token: your API key). Tool list and constraints are in the agent docs — notably, no MCP tool accepts a Stripe key; connecting via restricted key is direct HTTPS only.