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
| Method | Path | Auth | What it does |
|---|---|---|---|
POST | /v1/signup | — | Request a verification code. Always 202, identical body (no account enumeration). |
POST | /v1/verify | — | Exchange the emailed 8-char code for the API key — shown exactly once. |
GET | /v1/me | API key | Account state, plan, scopes, limits, and publish_blockers[]. |
POST | /v1/stripe/connect | API key | Connect via read-only restricted key. Direct HTTPS only — never MCP. Rejects sk_ keys. |
POST | /v1/stripe/confirm | API key | Publish authorization — the code from the connected Stripe account's own inbox. |
POST | /v1/stripe/connect_url | API key | One-time OAuth URL (15 min). A human must open it; OAuth skips the confirm step. |
GET | /v1/stripe/connection | API key | Connection mode, status (active/degraded/revoked), livemode, last sync, cursor age. |
GET | /v1/walls | API key | List walls; each carries published: true|false plus a reason when false. |
POST | /v1/walls | API key | Create a wall. Accepts Idempotency-Key. |
GET | /v1/walls/:public_id | — | Public wall JSON. Bare 404 until publishable. Paginated (limit 60, cursor). |
GET | /v1/walls/demo | — | Public demo wall — same shape, no signup. Integrate against this first. |
POST | /v1/domains | API key | Manually add a domain. Accepts Idempotency-Key. |
POST | /v1/exclusions | API key | Exclude a domain from all walls — applies at serve time, never waits on a sync. |
DELETE | /v1/exclusions/:domain | API key | Remove an exclusion (works on every plan). |
GET | /v1/sync/status | API key | Sync funnel counts; poll latest_job.state after connecting. |
POST | /v1/sync/refresh | API key | On-demand sync, 1/hour/connection (scheduled sync runs daily). |
POST | /v1/billing/checkout_url | API key | Stripe Checkout URL for Pro — a human opens it and pays. |
POST | /v1/billing/portal_url | API key | Stripe Billing Portal URL for accounts that have paid before. |
POST | /v1/unpublish_all | API key | Panic button: every wall 404s immediately, hard cache purge. |
POST | /v1/republish | API key (admin) | Clear the panic button (deliberately harder than unpublishing). |
GET | /health | — | Service health: db / stripe / logodev checks. |
GET | /logo/:domain.png | — | Logo 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
| Endpoint | Limit |
|---|---|
POST /v1/signup | 3 codes/hour, 10/day per email; per-IP limits apply |
POST /v1/verify | 15 lifetime failed codes per account, then verification locks 24h |
POST /v1/stripe/confirm | Same budget construction as /v1/verify |
POST /v1/billing/checkout_url | 5/hour per account |
POST /v1/sync/refresh | 1/hour per connection (scheduled sync also runs daily) |
GET /v1/walls/:public_id | Cached: s-maxage=60, stale-while-revalidate=300 |
| Other authed /v1 endpoints | Generous; 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.