A small REST API over the Outwink Postgres. Manage lists, add leads to meme campaigns, export results as paginated CSV. One header, one curl per call — no SDK required.
Copy these docs as Markdown to paste into AI tools — includes example responses, errors, and curl for every endpoint.
Treat your API key like a password. Never embed it in browser code in production — call this API from a server you control.
Overview
The Outwink Public API exposes a small set of endpoints over Supabase Postgres. Adding leads costs 1 credit per lead; everything else is free. There is no rate limiting — your credit balance is the only throttle.
This page auto-detects its own origin via window.location.origin, so every curl example uses the URL you loaded the page from. Same payload works on localhost, Railway previews, and any custom domain.
Authentication
Every /v1/* request must include your API key in the X-API-Key header:
X-API-Key: <your-api-key>
The key is a UUID. Get it from the Outwink Settings panel, or rotate it programmatically via POST /v1/auth/rotate-key.
No header → 401 missing_authorization.
Header present but key doesn't resolve → 401 invalid_api_key.
Errors
Every non-2xx response uses the same flat envelope:
GET /v1/lists takes page (default 1) and size (default 50, max 200). The response includes a pagination object: { page, size, total, last_page, has_next, has_prev }.
GET /v1/lists/:id/csv takes the same page/size (default 10000, max 10000) and emits these response headers so generic CSV importers can walk pages without parsing the body:
X-Total-Count, X-Page, X-Page-Size, X-Last-Page
Link per RFC 5988 with rel="first", rel="last", plus rel="next" / rel="prev" when applicable.
Endpoints
GETGet account info
/v1/meAccount
Returns your user record (id, email, full name, current credit balance) plus your most relevant subscription. subscription is null when you have no row in subscriptions.
Paginated summary of every list you own, newest first. Each row includes a lead_count. Use page and size to walk the collection; the response includes a pagination object so you don't have to compute it.
Returns one list, including the template's variables array (in declared order) and the image_extension (gif if render_spec.has_gif === true, otherwise png). Use these when constructing the body for Generate image.
Renames the list. The new name is trimmed and must be 1–120 characters; otherwise the call fails with 400 invalid_input. Nothing else (type, render spec, leads) is touched.
`name` is empty or longer than 120 chars after trim.
404
list_not_found
List doesn't exist or isn't owned by you.
401
missing_authorization
No `X-API-Key` header.
401
invalid_api_key
The key didn't resolve to a user.
500
internal_error
Anything unexpected; logged server-side.
Live response
Click Try it to send the request.
DELETEDelete a list
/v1/lists/:list_idLists
Removes the list and every lead it owns. Ownership is verified up-front so non-owners get 404 list_not_found just like callers asking for a non-existent UUID.
Adds one lead to a meme list and renders its personalised image. Costs 1 credit. variables is a flat object whose keys are the template variable names. Missing keys are not an error — they're inserted as null and reported back in missing_variables; extra keys land in ignored_variables. AI and ice-breaker lists are rejected with 400 list_type_not_supported.
List is `ai` or `ice_breaker`; only `meme` is supported here.
402
insufficient_credits
`details: { cost, available }`. Top up and retry.
404
list_not_found
List doesn't exist or isn't owned by you.
401
missing_authorization
No `X-API-Key` header.
401
invalid_api_key
The key didn't resolve to a user.
500
internal_error
Anything unexpected; logged server-side.
Live response
Click Try it to send the request.
GETExport leads as CSV
/v1/lists/:list_id/csvLeads
Streams the leads in a list as a paginated CSV. The first column is tracking_id, the second is image_url, and the remaining columns are the template variables in declared order. The response also sets pagination headers and an RFC 5988 Link header so generic CSV importers can walk the pages without parsing the body. No credits are charged. size is capped at 10000.
Generates a fresh API key and overwrites the old one in place. The old key stops authenticating immediately — no grace period — so update any stored credentials before invoking this. Authenticate with the current key.