{"openapi":"3.1.0","info":{"title":"UseWait API","version":"1.0.0","summary":"Create and manage product waitlists programmatically.","description":"UseWait builds hosted waitlist pages. This API creates a waitlist, customizes its page, connects a custom domain, manages confirmation emails and reads signups.\n\nAuthenticate every request with `Authorization: Bearer uw_live_...`. Create keys in Dashboard > Settings > API Keys; they are available on the free tier. Keys carry scopes, so a key can be limited to exactly the operations an agent needs.\n\nThe same capabilities are exposed over MCP at /api/mcp/mcp (Streamable HTTP) for agents that speak the Model Context Protocol.","contact":{"name":"UseWait support","url":"https://usewait.com/contact"},"license":{"name":"Proprietary","url":"https://usewait.com/terms"}},"servers":[{"url":"https://usewait.com","description":"Production"}],"externalDocs":{"description":"Developer documentation","url":"https://usewait.com/developers"},"tags":[{"name":"Account","description":"Plan, usage and quota."},{"name":"Waitlists","description":"Create and manage waitlists and their pages."},{"name":"Entries","description":"Read signups."},{"name":"Email templates","description":"Confirmation emails sent to new signups."},{"name":"Integrations","description":"Custom domains, Turnstile keys and bring-your-own database."},{"name":"Assets","description":"Image uploads to the CDN."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key created in Dashboard > Settings > API Keys, sent as `Authorization: Bearer uw_live_...`. The `x-api-key` header is accepted as an alternative. Each key carries a subset of the scopes below; a key missing a scope gets 403 with `code: insufficient_scope`."},"oauth2":{"type":"oauth2","description":"OAuth 2.1 with PKCE and dynamic client registration, used by MCP clients. Discovery lives at /.well-known/oauth-authorization-server.","flows":{"authorizationCode":{"authorizationUrl":"https://usewait.com/api/auth/mcp/authorize","tokenUrl":"https://usewait.com/api/auth/mcp/token","refreshUrl":"https://usewait.com/api/auth/mcp/token","scopes":{"account:read":"Read account, plan and usage information.","waitlists:read":"List and read waitlists, including their page code.","waitlists:write":"Create, update and delete waitlists.","entries:read":"Read waitlist signups.","templates:read":"List and read confirmation email templates.","templates:write":"Create, update and delete email templates.","domains:write":"Connect and disconnect custom domains, and manage Turnstile and database settings.","assets:write":"Upload images to the CDN."}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human readable description of what went wrong."},"code":{"type":"string","description":"Stable machine readable code, present on errors an agent can act on.","examples":["insufficient_scope"]},"resolution":{"type":"string","description":"What the caller should do to resolve this error."},"requiredScope":{"type":"string","description":"Scope the key was missing, on a 403."},"grantedScopes":{"type":"array","items":{"type":"string"},"description":"Scopes the key does carry, on a 403."},"upgradeUrl":{"type":"string","format":"uri","description":"On a 402, where the user licenses the waitlist."},"priceUsd":{"type":"number","description":"On a 402, the one-time price in USD."},"details":{"type":"array","description":"On a 400, the specific fields that failed validation.","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}},"Waitlist":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","description":"URL segment; the page is live at /w/{slug}."},"name":{"type":"string"},"description":{"type":"string","nullable":true},"licensed":{"type":"boolean","description":"Whether this waitlist has been licensed with the one-time payment."},"seoTitle":{"type":"string","nullable":true},"seoDescription":{"type":"string","nullable":true},"seoKeywords":{"type":"string","nullable":true},"ogImage":{"type":"string","format":"uri","nullable":true},"referralEnabled":{"type":"boolean"},"referralBoost":{"type":"integer","description":"Positions gained per successful referral."},"referralMessage":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"Entry":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"name":{"type":"string","nullable":true},"position":{"type":"integer","description":"Place in the queue, 1 based."},"referralCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"EmailTemplate":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subject":{"type":"string","description":"May contain {{waitlistName}}, {{description}}, {{position}}, {{referralLink}}."},"html":{"type":"string","description":"Full inline-styled HTML document."},"waitlistIds":{"type":"array","items":{"type":"string","format":"uuid"}},"createdAt":{"type":"string","format":"date-time"}}},"WaitlistCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","description":"Lowercase letters, digits and hyphens. Generated from the name when omitted."},"description":{"type":"string","maxLength":500},"reactCode":{"type":"string","maxLength":200000,"description":"The page itself: a single function GeneratedWaitlist(props) built with React.createElement (no JSX), rendered in a sandbox with React in scope. Call props.onSubmit({ email, name }) to submit a signup. Omit to get the default template."},"seoTitle":{"type":"string","maxLength":70},"seoDescription":{"type":"string","maxLength":160},"seoKeywords":{"type":"string","maxLength":255},"ogImage":{"type":"string","format":"uri","description":"Social preview image. Use a PNG or JPG at 1200x630; SVG is rejected here."},"referralEnabled":{"type":"boolean"},"referralBoost":{"type":"integer","minimum":1,"maximum":100},"referralMessage":{"type":"string","maxLength":500}}},"WaitlistUpdate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"slug":{"type":"string","description":"Lowercase letters, digits and hyphens. Generated from the name when omitted."},"description":{"type":"string","maxLength":500},"reactCode":{"type":"string","maxLength":200000,"description":"The page itself: a single function GeneratedWaitlist(props) built with React.createElement (no JSX), rendered in a sandbox with React in scope. Call props.onSubmit({ email, name }) to submit a signup. Omit to get the default template."},"seoTitle":{"type":"string","maxLength":70},"seoDescription":{"type":"string","maxLength":160},"seoKeywords":{"type":"string","maxLength":255},"ogImage":{"type":"string","format":"uri","description":"Social preview image. Use a PNG or JPG at 1200x630; SVG is rejected here."},"referralEnabled":{"type":"boolean"},"referralBoost":{"type":"integer","minimum":1,"maximum":100},"referralMessage":{"type":"string","maxLength":500}}}}},"paths":{"/api/v1":{"get":{"operationId":"getApiIndex","tags":["Account"],"summary":"Discovery document","description":"Unauthenticated index of the API and the MCP endpoint, so an agent can self-configure before it has a key.","security":[],"responses":{"200":{"description":"The discovery document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/me":{"get":{"operationId":"getAccount","tags":["Account"],"summary":"Get account, plan and usage","description":"Billing model, how many waitlists exist, how many are licensed, and remaining AI generation quota.","security":[{"apiKey":["account:read"]}],"responses":{"200":{"description":"Account information.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists":{"get":{"operationId":"listWaitlists","tags":["Waitlists"],"summary":"List waitlists","description":"Every waitlist on the account, without the page code.","security":[{"apiKey":["waitlists:read"]}],"responses":{"200":{"description":"The account's waitlists.","content":{"application/json":{"schema":{"type":"object","properties":{"waitlists":{"type":"array","items":{"$ref":"#/components/schemas/Waitlist"}}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createWaitlist","tags":["Waitlists"],"summary":"Create a waitlist","description":"Creates a waitlist and publishes it at /w/{slug} immediately. Omit reactCode to get the default template and iterate with updateWaitlist.","security":[{"apiKey":["waitlists:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistCreate"}}}},"responses":{"201":{"description":"The created waitlist.","content":{"application/json":{"schema":{"type":"object","properties":{"waitlist":{"$ref":"#/components/schemas/Waitlist"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"The waitlist id (UUID) or its slug. Both are accepted.","schema":{"type":"string"}}],"get":{"operationId":"getWaitlist","tags":["Waitlists"],"summary":"Get a waitlist","description":"One waitlist, including its full page code.","security":[{"apiKey":["waitlists:read"]}],"responses":{"200":{"description":"The waitlist.","content":{"application/json":{"schema":{"type":"object","properties":{"waitlist":{"$ref":"#/components/schemas/Waitlist"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateWaitlist","tags":["Waitlists"],"summary":"Update a waitlist","description":"Every field is optional; only what you send changes.","security":[{"apiKey":["waitlists:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistUpdate"}}}},"responses":{"200":{"description":"The updated waitlist.","content":{"application/json":{"schema":{"type":"object","properties":{"waitlist":{"$ref":"#/components/schemas/Waitlist"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteWaitlist","tags":["Waitlists"],"summary":"Delete a waitlist","description":"Deletes the waitlist and every signup on it. Not reversible.","security":[{"apiKey":["waitlists:write"]}],"responses":{"200":{"description":"Deletion result.","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists/{id}/entries":{"parameters":[{"name":"id","in":"path","required":true,"description":"The waitlist id (UUID) or its slug. Both are accepted.","schema":{"type":"string"}}],"get":{"operationId":"listEntries","tags":["Entries"],"summary":"List signups","description":"Signups for one waitlist, newest first.","security":[{"apiKey":["entries:read"]}],"parameters":[{"name":"limit","in":"query","description":"How many to return. Maximum 200.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"offset","in":"query","description":"How many to skip, for paging.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"The signups.","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/Entry"}},"total":{"type":"integer"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists/{id}/domain":{"parameters":[{"name":"id","in":"path","required":true,"description":"The waitlist id (UUID) or its slug. Both are accepted.","schema":{"type":"string"}}],"get":{"operationId":"getCustomDomain","tags":["Integrations"],"summary":"Get custom domain status","description":"Current domain state plus the CNAME record the domain owner must create, pointing at the fallback origin waas.usewait.com. Poll while the domain reports verifying.","security":[{"apiKey":["waitlists:read"]}],"parameters":[{"name":"check","in":"query","description":"Inspect a candidate domain without configuring it.","schema":{"type":"string"}}],"responses":{"200":{"description":"Domain state and the required DNS record.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"connectCustomDomain","tags":["Integrations"],"summary":"Connect a custom domain","description":"Registers the domain with Cloudflare for SaaS and returns the exact CNAME to create. SSL is issued automatically within a few minutes.","security":[{"apiKey":["domains:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string","examples":["waitlist.example.com"]}}}}}},"responses":{"200":{"description":"The domain was registered.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Registration failed; `error` explains why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"disconnectCustomDomain","tags":["Integrations"],"summary":"Disconnect the custom domain","description":"The /w/{slug} URL keeps working.","security":[{"apiKey":["domains:write"]}],"responses":{"200":{"description":"Disconnected.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists/{id}/turnstile":{"parameters":[{"name":"id","in":"path","required":true,"description":"The waitlist id (UUID) or its slug. Both are accepted.","schema":{"type":"string"}}],"get":{"operationId":"getTurnstileStatus","tags":["Integrations"],"summary":"Get Turnstile key status","description":"Whether custom Cloudflare Turnstile keys are set. Secrets are never returned.","security":[{"apiKey":["waitlists:read"]}],"responses":{"200":{"description":"Turnstile status.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"setTurnstileKeys","tags":["Integrations"],"summary":"Set Turnstile keys","description":"Omit a field to leave it unchanged; pass null to clear it.","security":[{"apiKey":["domains:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"siteKey":{"type":"string","nullable":true},"secretKey":{"type":"string","nullable":true}}}}}},"responses":{"200":{"description":"Keys updated.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"clearTurnstileKeys","tags":["Integrations"],"summary":"Clear Turnstile keys","description":"Reverts the waitlist to the shared UseWait Turnstile keys.","security":[{"apiKey":["domains:write"]}],"responses":{"200":{"description":"Keys cleared.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/waitlists/{id}/database":{"parameters":[{"name":"id","in":"path","required":true,"description":"The waitlist id (UUID) or its slug. Both are accepted.","schema":{"type":"string"}}],"get":{"operationId":"getDatabaseStatus","tags":["Integrations"],"summary":"Get signup storage status","description":"Whether signups go to the internal database or the account's own, and the table name.","security":[{"apiKey":["waitlists:read"]}],"responses":{"200":{"description":"Storage status.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"connectExternalDatabase","tags":["Integrations"],"summary":"Connect your own database","description":"Creates the waitlist_{slug} table in the given Postgres or MySQL database and stores signups there. Use testOnly to verify connectivity without persisting anything.","security":[{"apiKey":["domains:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["dbType","connectionString"],"properties":{"dbType":{"type":"string","enum":["postgres","mysql"]},"connectionString":{"type":"string"},"testOnly":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Connected, or the test succeeded.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Could not connect; `error` explains why.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"detachExternalDatabase","tags":["Integrations"],"summary":"Detach the external database","description":"New signups fall back to the internal database.","security":[{"apiKey":["domains:write"]}],"responses":{"200":{"description":"Detached.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/email-templates":{"get":{"operationId":"listEmailTemplates","tags":["Email templates"],"summary":"List email templates","description":"Templates plus a `format` object documenting the available {{variables}} and the HTML rules.","security":[{"apiKey":["templates:read"]}],"responses":{"200":{"description":"Templates and the authoring format.","content":{"application/json":{"schema":{"type":"object","properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/EmailTemplate"}},"format":{"type":"object"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createEmailTemplate","tags":["Email templates"],"summary":"Create an email template","description":"html must be a full inline-styled document. Linking waitlistIds makes new signups on those waitlists receive it.","security":[{"apiKey":["templates:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","subject","html"],"properties":{"name":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string"},"waitlistIds":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"responses":{"201":{"description":"The created template.","content":{"application/json":{"schema":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/EmailTemplate"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/email-templates/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"The template id.","schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getEmailTemplate","tags":["Email templates"],"summary":"Get an email template","description":"One template, including its full HTML.","security":[{"apiKey":["templates:read"]}],"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/EmailTemplate"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateEmailTemplate","tags":["Email templates"],"summary":"Update an email template","description":"Sending waitlistIds replaces the assignment set rather than adding to it.","security":[{"apiKey":["templates:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string"},"waitlistIds":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"responses":{"200":{"description":"The updated template.","content":{"application/json":{"schema":{"type":"object","properties":{"template":{"$ref":"#/components/schemas/EmailTemplate"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteEmailTemplate","tags":["Email templates"],"summary":"Delete an email template","description":"Waitlists linked to it fall back to the default confirmation email.","security":[{"apiKey":["templates:write"]}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/assets":{"post":{"operationId":"uploadAsset","tags":["Assets"],"summary":"Upload an image","description":"Send multipart/form-data with a `file` field, or JSON with base64 data. Maximum 5MB. Allowed: jpeg, png, gif, webp, svg. Returns the CDN url to use as ogImage or inside page code.","security":[{"apiKey":["assets:write"]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}},"application/json":{"schema":{"type":"object","required":["data","contentType"],"properties":{"data":{"type":"string","description":"Base64 encoded file contents."},"contentType":{"type":"string","examples":["image/png"]},"fileName":{"type":"string"}}}}}},"responses":{"200":{"description":"The uploaded asset.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}},"400":{"description":"Validation failed. `details` names the offending fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but lacks the scope this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"File larger than 5MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded (120 requests/minute per account).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"x-scopes":{"account:read":"Read account, plan and usage information.","waitlists:read":"List and read waitlists, including their page code.","waitlists:write":"Create, update and delete waitlists.","entries:read":"Read waitlist signups.","templates:read":"List and read confirmation email templates.","templates:write":"Create, update and delete email templates.","domains:write":"Connect and disconnect custom domains, and manage Turnstile and database settings.","assets:write":"Upload images to the CDN."},"x-mcp":{"endpoint":"https://usewait.com/api/mcp/mcp","transport":"streamable-http","description":"The same capabilities as MCP tools, for agents that speak the protocol."},"x-rate-limit":{"requests":120,"window":"1 minute","scope":"per account"}}