{"openapi":"3.1.0","info":{"title":"Nordva Launch API","version":"0.1.0","description":"Changelog, waitlist, feedback triage, notifications, read-only Stripe revenue, contacts and attribution for your product, behind one API key and one MCP server.","contact":{"url":"https://launch.nordva.dev"}},"servers":[{"url":"https://api.nordva.dev"}],"components":{"securitySchemes":{"SecretApiKey":{"type":"http","scheme":"bearer","bearerFormat":"nv_live_[32 chars]","description":"Secret key — full read/write access. Server-side only. Legacy format `sk_live_*` is also accepted for backward compatibility. Obtain from Dashboard → API Keys."},"PublishableApiKey":{"type":"http","scheme":"bearer","bearerFormat":"nv_pub_live_[32 chars]","description":"Publishable key — browser-safe. Write-only on public endpoints (waitlist signups, changelog subscribers, feedback, notification reads). Cannot access any read or admin endpoints. Obtain from Dashboard → API Keys."},"ClerkJWT":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Clerk RS256 JWT for dashboard endpoints. Verified against Clerk's JWKS. Not interchangeable with API keys."}},"schemas":{"ChangelogEntry":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"public_url":{"type":"string","format":"uri"}},"required":["id","project_id","title","body_markdown","version","category","status","scheduled_at","published_at","created_at","updated_at","public_url"],"additionalProperties":false},"CreateChangelogEntryInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"type":"string","minLength":1,"maxLength":64},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"scheduled_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"notify_subscribers":{"type":"boolean"}},"required":["title","body_markdown","category"],"additionalProperties":false},"UpdateChangelogEntryInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"type":"string","minLength":1,"maxLength":64},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"status":{"type":"string","const":"published"}},"additionalProperties":false},"CreateSubscriberInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["email"],"additionalProperties":false},"Subscriber":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","pattern":"^sub_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"confirmed":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["id","project_id","email","confirmed","created_at"],"additionalProperties":false},"SetupCheck":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"project_slug":{"type":"string"},"project_name":{"type":"string"},"plan":{"type":"string","enum":["free","indie","builder","scale"]},"features_enabled":{"type":"object","properties":{"changelog":{"type":"boolean"},"waitlist":{"type":"boolean"},"feedback":{"type":"boolean"},"notifications":{"type":"boolean"},"email_notifications":{"type":"boolean"},"custom_domain":{"type":"boolean"}},"required":["changelog","waitlist","feedback","notifications","email_notifications","custom_domain"],"additionalProperties":false},"limits":{"type":"object","properties":{"changelog_entries_remaining":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"subscribers_max":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["changelog_entries_remaining","subscribers_max"],"additionalProperties":false},"plan_details":{"type":"object","properties":{"description":{"type":"string"},"locked_features":{"type":"array","items":{"type":"string"}},"upgrade_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"changelog_public_url":{"type":"string","format":"uri"}},"required":["description","locked_features","upgrade_url","changelog_public_url"],"additionalProperties":false}},"required":["project_id","project_slug","project_name","plan","features_enabled","limits","plan_details"],"additionalProperties":false},"ErrorEnvelope":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"PublicChangelogEntry":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"public_url":{"type":"string","format":"uri"}},"required":["id","title","body_markdown","version","category","published_at","public_url"],"additionalProperties":false},"CreateWaitlistSignupInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"referrer_code":{"type":"string","pattern":"^[A-Za-z0-9]{8}$"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"source":{"type":"object","properties":{"referrer":{"type":"string","maxLength":2048},"utm_source":{"type":"string","maxLength":255},"utm_medium":{"type":"string","maxLength":255},"utm_campaign":{"type":"string","maxLength":255},"landing_path":{"type":"string","maxLength":512}},"additionalProperties":false},"turnstile_token":{"type":"string"}},"required":["email"],"additionalProperties":false},"WaitlistSignup":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"signup_id":{"type":"string","pattern":"^ws_[0-9A-HJKMNP-TV-Z]{26}$"},"position":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"referral_code":{"type":"string","pattern":"^[A-Za-z0-9]{8}$"},"referral_link":{"type":"string","format":"uri"},"referrer_credited":{"type":"boolean"},"confirmation_email_sent":{"type":"boolean"},"already_registered":{"type":"boolean"},"project_plan":{"type":"string","enum":["free","indie","builder"]}},"required":["signup_id","position","referral_code","referral_link","referrer_credited","confirmation_email_sent","already_registered","project_plan"],"additionalProperties":false},"WaitlistStats":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"total_signups":{"type":"integer","minimum":0,"maximum":9007199254740991},"confirmed_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"invited_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"via_referral_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"referral_conversion_rate":{"type":"number","minimum":0,"maximum":1},"top_referrers":{"type":"array","items":{"type":"object","properties":{"signup_id":{"type":"string","pattern":"^ws_[0-9A-HJKMNP-TV-Z]{26}$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"referral_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["signup_id","email","referral_count"],"additionalProperties":false}}},"required":["total_signups","confirmed_count","invited_count","via_referral_count","referral_conversion_rate","top_referrers"],"additionalProperties":false},"CreateFeedbackInput":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"feedback_text":{"type":"string","minLength":10,"maxLength":2000},"user_id":{"type":"string","minLength":1,"maxLength":256},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"page_url":{"type":"string","maxLength":2048,"format":"uri"},"category_hint":{"type":"string","enum":["bug","feature_request","praise","billing","support"]}},"required":["feedback_text"],"additionalProperties":false}}},"security":[{"SecretApiKey":[]}],"paths":{"/v1/_health":{"get":{"operationId":"healthCheck","summary":"Health check","security":[],"responses":{"200":{"description":"OK"}},"tags":["Project"]}},"/v1/setup-check":{"get":{"operationId":"setupCheck","summary":"Auth + plan introspection","description":"Returns the project, plan, feature flags, and remaining quota for the bearer's API key. **Call this first on every integration** to verify your key is valid and confirm which features are enabled on your plan.\n\nAuth: Secret key (`nv_live_*` or `nv_test_*`).","responses":{"200":{"description":"Setup info","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"project_slug":{"type":"string"},"project_name":{"type":"string"},"plan":{"type":"string","enum":["free","indie","builder","scale"]},"features_enabled":{"type":"object","properties":{"changelog":{"type":"boolean"},"waitlist":{"type":"boolean"},"feedback":{"type":"boolean"},"notifications":{"type":"boolean"},"email_notifications":{"type":"boolean"},"custom_domain":{"type":"boolean"}},"required":["changelog","waitlist","feedback","notifications","email_notifications","custom_domain"],"additionalProperties":false},"limits":{"type":"object","properties":{"changelog_entries_remaining":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"subscribers_max":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["changelog_entries_remaining","subscribers_max"],"additionalProperties":false},"plan_details":{"type":"object","properties":{"description":{"type":"string"},"locked_features":{"type":"array","items":{"type":"string"}},"upgrade_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"changelog_public_url":{"type":"string","format":"uri"}},"required":["description","locked_features","upgrade_url","changelog_public_url"],"additionalProperties":false}},"required":["project_id","project_slug","project_name","plan","features_enabled","limits","plan_details"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Project"]}},"/v1/waitlist/signups":{"post":{"operationId":"createWaitlistSignup","summary":"Add an email to the waitlist","description":"Adds a new signup to the project's waitlist and returns the user's queue position and a referral code to share.\n\nAuth: **Publishable key** (`nv_pub_live_*`) — call this directly from browser JavaScript. No backend proxy required.\n\nCORS: `Access-Control-Allow-Origin: *` — safe to call from any frontend origin.\n\nReturns 409 with `DUPLICATE_SIGNUP` if the email already exists.","x-code-samples":[{"lang":"TypeScript","label":"Browser (publishable key)","source":"const res = await fetch(\"https://api.nordva.dev/v1/waitlist/signups\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer nv_pub_live_YOUR_PUBLISHABLE_KEY\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ email: \"user@example.com\" }),\n});\nif (res.status === 409) {\n  // Already on the waitlist\n}\nconst { data } = await res.json();\n// data.position — queue position (1-based)\n// data.referral_code — shareable referral code"}],"security":[{"PublishableApiKey":[]},{"SecretApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWaitlistSignupInput"}}}},"responses":{"201":{"description":"Signup created","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"signup_id":{"type":"string","pattern":"^ws_[0-9A-HJKMNP-TV-Z]{26}$"},"position":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"referral_code":{"type":"string","pattern":"^[A-Za-z0-9]{8}$"},"referral_link":{"type":"string","format":"uri"},"referrer_credited":{"type":"boolean"},"confirmation_email_sent":{"type":"boolean"},"already_registered":{"type":"boolean"},"project_plan":{"type":"string","enum":["free","indie","builder"]}},"required":["signup_id","position","referral_code","referral_link","referrer_credited","confirmation_email_sent","already_registered","project_plan"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]},"get":{"operationId":"listWaitlistSignups","summary":"List all waitlist signups","description":"Returns paginated signups for the project. Includes email, position, referral stats, confirmation and invite status.\n\nAuth: Secret key only (`nv_live_*` or `nv_test_*`). Publishable keys receive `403 KEY_INSUFFICIENT_PERMISSIONS`.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"email","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["waiting","invited","unsubscribed"]}}],"responses":{"200":{"description":"Paginated signup list"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/signups/resend-confirmation":{"post":{"operationId":"resendWaitlistConfirmation","summary":"Resend the confirmation email to a pending signup","description":"Re-sends the double-opt-in confirmation email. Rate-limited to 1 resend per 5 minutes per email.\n\nAuth: Secret key. Requires Indie or Builder plan (plan that has `sendsConfirmationEmail: true`).","security":[{"SecretApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Resent (or already confirmed)"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"429":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/stats":{"get":{"operationId":"getWaitlistStats","summary":"Get waitlist aggregate stats","description":"Returns total signups, confirmed count, invited count, and top-level referral stats for the project.\n\nAuth: Secret key only.","responses":{"200":{"description":"Stats","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"total_signups":{"type":"integer","minimum":0,"maximum":9007199254740991},"confirmed_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"invited_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"via_referral_count":{"type":"integer","minimum":0,"maximum":9007199254740991},"referral_conversion_rate":{"type":"number","minimum":0,"maximum":1},"top_referrers":{"type":"array","items":{"type":"object","properties":{"signup_id":{"type":"string","pattern":"^ws_[0-9A-HJKMNP-TV-Z]{26}$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"referral_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["signup_id","email","referral_count"],"additionalProperties":false}}},"required":["total_signups","confirmed_count","invited_count","via_referral_count","referral_conversion_rate","top_referrers"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/leaderboard":{"get":{"operationId":"getWaitlistLeaderboard","summary":"Top referrers leaderboard","description":"Returns the top 50 referrers ordered by referral count. Emails are partially masked.\n\nAuth: Secret key only.","responses":{"200":{"description":"Leaderboard","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"rank":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"masked_email":{"type":"string"},"referral_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["rank","masked_email","referral_count"],"additionalProperties":false}},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/invites":{"post":{"operationId":"sendWaitlistInvites","summary":"Send invite emails to waiting signups","description":"Moves signups from `waiting` to `invited` status and fires invite emails. Two modes: `{ count: N }` takes the next N by FIFO; `{ specific_email: \"x@y.com\" }` invites one specific signup.\n\nAuth: Secret key. Indie or Builder plan required.","security":[{"SecretApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":500},"specific_email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Invite batch result with `invited_count`"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"429":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/settings":{"get":{"operationId":"getWaitlistSettings","summary":"Read waitlist settings","description":"Returns current settings: whether signups are open and any custom landing page copy.\n\nAuth: Secret key only.","responses":{"200":{"description":"Settings object"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]},"patch":{"operationId":"updateWaitlistSettings","summary":"Update waitlist settings","description":"Pause or resume signup intake, and set custom landing page headline and body copy. Pass `null` to clear custom text.\n\nAuth: Secret key only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accepting_signups":{"type":"boolean"},"header_text":{"type":["string","null"],"maxLength":120},"body_text":{"type":["string","null"],"maxLength":300}}}}}},"responses":{"200":{"description":"Updated settings"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/export":{"get":{"operationId":"exportWaitlist","summary":"Generate a signed export download URL","description":"Generates the waitlist data as CSV or JSON, stores it for 15 minutes, and returns a time-limited download URL.\n\nAuth: Secret key. Indie or Builder plan required (`canExport: true`).","parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["csv","json"],"default":"csv"}},{"name":"include_flagged","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Export info with `download_url` valid for 15 minutes"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/signups/by-token/{token}":{"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"operationId":"unsubscribeWaitlistSignup","summary":"Hard-delete a signup via token (GDPR Art. 17)","description":"Public endpoint — no auth required. Permanently deletes the signup row and all associated confirmation tokens. This is the GDPR right-to-erasure handler linked from the confirmation email unsubscribe footer.","security":[],"responses":{"200":{"description":"Unsubscribed (always 200, even if token not found)"}},"tags":["Waitlist"]}},"/v1/changelog/entries":{"post":{"operationId":"createChangelogEntry","summary":"Create or schedule a changelog entry","description":"Creates a new changelog entry, optionally notifying email subscribers immediately.\n\nAuth: Secret key only (`nv_live_*`). This endpoint modifies project content and must not be called from a browser.\n\nIdempotency: Pass `Idempotency-Key` header to safely retry without creating duplicates.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Replay-safe identifier. Same key + same body returns the original response. Same key + different body returns 422."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateChangelogEntryInput"}}}},"responses":{"201":{"description":"Entry created","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"public_url":{"type":"string","format":"uri"}},"required":["id","project_id","title","body_markdown","version","category","status","scheduled_at","published_at","created_at","updated_at","public_url"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"422":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]},"get":{"operationId":"listChangelogEntries","summary":"List published changelog entries","description":"Returns published entries in reverse-chronological order. **Auth: None — this endpoint is public.** No `Authorization` header needed.\n\nCORS: `Access-Control-Allow-Origin: *` — call directly from frontend JavaScript to render your changelog.","x-code-samples":[{"lang":"TypeScript","label":"Browser (no auth)","source":"const res = await fetch(\n  \"https://api.nordva.dev/v1/changelog/entries?limit=5\"\n);\nconst { data } = await res.json();\n// data is an array of changelog entries"}],"security":[],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"tag","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of entries","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"public_url":{"type":"string","format":"uri"}},"required":["id","project_id","title","body_markdown","version","category","status","scheduled_at","published_at","created_at","updated_at","public_url"],"additionalProperties":false}},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]}},"/v1/changelog/entries/{entry_id}":{"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string"},"description":"Entry ID or slug"}],"get":{"operationId":"getChangelogEntry","summary":"Get a single changelog entry","description":"Returns a single entry by ID or slug. **Auth: None — public endpoint.**","security":[],"responses":{"200":{"description":"Entry","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"public_url":{"type":"string","format":"uri"}},"required":["id","project_id","title","body_markdown","version","category","status","scheduled_at","published_at","created_at","updated_at","public_url"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]},"patch":{"operationId":"updateChangelogEntry","summary":"Update a draft or scheduled entry","description":"Updates title, body, tags, or scheduled_at. Published entries cannot be edited.\n\nAuth: Secret key only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateChangelogEntryInput"}}}},"responses":{"200":{"description":"Updated entry","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"status":{"type":"string","enum":["draft","published","scheduled","archived"]},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"public_url":{"type":"string","format":"uri"}},"required":["id","project_id","title","body_markdown","version","category","status","scheduled_at","published_at","created_at","updated_at","public_url"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]},"delete":{"operationId":"archiveChangelogEntry","summary":"Soft-archive a changelog entry","description":"Removes the entry from the public feed immediately. The record is retained in the database.\n\nAuth: Secret key only.","responses":{"200":{"description":"Archived"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]}},"/v1/changelog/subscribers":{"post":{"operationId":"subscribeToChangelog","summary":"Subscribe an email to the changelog","description":"Adds an email subscriber to receive changelog notification emails whenever a new entry is published with `notify_subscribers: true`.\n\nAuth: **Publishable key** (`nv_pub_live_*`) — browser-safe.\n\nCORS: `Access-Control-Allow-Origin: *`.","x-code-samples":[{"lang":"TypeScript","label":"Browser (publishable key)","source":"const res = await fetch(\"https://api.nordva.dev/v1/changelog/subscribers\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer nv_pub_live_YOUR_KEY\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ email: \"user@example.com\" }),\n});\n// 201: subscribed, 409: already subscribed"}],"security":[{"PublishableApiKey":[]},{"SecretApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSubscriberInput"}}}},"responses":{"201":{"description":"Subscriber created","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","pattern":"^sub_[0-9A-HJKMNP-TV-Z]{26}$"},"project_id":{"type":"string","pattern":"^prj_[0-9A-HJKMNP-TV-Z]{26}$"},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"confirmed":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["id","project_id","email","confirmed","created_at"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]}},"/v1/changelog/subscribers/by-token/{token}":{"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"operationId":"unsubscribeFromChangelog","summary":"Unsubscribe via one-click token (no auth)","description":"Public endpoint — no auth required. Linked from the unsubscribe footer of every changelog notification email.","security":[],"responses":{"200":{"description":"Unsubscribed"}},"tags":["Changelog"]}},"/public/changelog/{project_slug}":{"parameters":[{"name":"project_slug","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"getPublicChangelog","summary":"Public changelog feed (by project slug)","description":"Returns all published entries for a project. No auth required.","security":[],"responses":{"200":{"description":"Published entries","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^ce_[0-9A-HJKMNP-TV-Z]{26}$"},"title":{"type":"string","minLength":1,"maxLength":200},"body_markdown":{"type":"string","minLength":1,"maxLength":50000},"version":{"anyOf":[{"type":"string"},{"type":"null"}]},"category":{"type":"string","enum":["feature","fix","improvement","security","breaking"]},"published_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"public_url":{"type":"string","format":"uri"}},"required":["id","title","body_markdown","version","category","published_at","public_url"],"additionalProperties":false}},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Changelog"]}},"/v1/feedback":{"post":{"operationId":"submitFeedback","summary":"Submit user feedback","description":"Submits free-text feedback. Claude Haiku classifies it into one of `bug | feature_request | praise | question | other` asynchronously (typically < 2 seconds). Routing to configured destinations (email, Slack, Linear, Discord) happens in the background.\n\nAuth: **Publishable key** (`nv_pub_live_*`) — browser-safe. No backend proxy needed.\n\nCORS: `Access-Control-Allow-Origin: *`.","x-code-samples":[{"lang":"TypeScript","label":"Browser (publishable key)","source":"const res = await fetch(\"https://api.nordva.dev/v1/feedback\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer nv_pub_live_YOUR_KEY\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    message: \"The dashboard is slow to load on mobile\",\n    user_id: \"user_abc123\",\n    url: window.location.href,\n  }),\n});\nconst { data } = await res.json();\n// data.category: \"bug\" | \"feature_request\" | \"praise\" | \"question\" | \"other\""}],"security":[{"PublishableApiKey":[]},{"SecretApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFeedbackInput"}}}},"responses":{"201":{"description":"Feedback submitted. Classification is async.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"category":{"type":"string"},"sentiment":{"type":"string"},"created_at":{"type":"string"}},"required":["id","category","sentiment","created_at"],"additionalProperties":false},"error":{"type":"null"},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Feedback"]},"get":{"operationId":"listFeedback","summary":"List feedback submissions","description":"Returns classified feedback. Filter by category or status.\n\nAuth: Secret key only.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["open","resolved","spam"]}}],"responses":{"200":{"description":"Paginated feedback list"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Feedback"]}},"/v1/feedback/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"operationId":"getFeedback","summary":"Get a single feedback submission","description":"Auth: Secret key only.","responses":{"200":{"description":"Feedback submission"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Feedback"]},"patch":{"operationId":"updateFeedback","summary":"Mark feedback reviewed or resolved, or correct its classification","description":"Set `status` to `reviewed` or `resolved`, and/or set `classification` to correct the classifier. A corrected classification gets confidence 1 and is not routed again. Returns the full submission.\n\nAuth: Secret key only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["reviewed","resolved"]},"classification":{"type":"string","enum":["bug","feature_request","praise","billing","support","uncategorised"]}}}}}},"responses":{"200":{"description":"Updated submission"},"400":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Feedback"]}},"/v1/notifications":{"post":{"operationId":"sendNotification","summary":"Send an in-app notification to a user","description":"Sends an in-app notification to a specific `user_id`. Your frontend polls `GET /v1/notifications/unread` to display it.\n\nAuth: Secret key only. **Builder plan required.**","x-code-samples":[{"lang":"TypeScript","label":"Server-side (secret key)","source":"// Server-side: fire after a background job completes\nawait fetch(\"https://api.nordva.dev/v1/notifications\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": \"Bearer nv_live_YOUR_SECRET_KEY\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    user_id: \"user_abc123\",\n    title: \"Export ready\",\n    body: \"Your CSV export has been generated.\",\n    action_url: \"https://app.yoursite.com/exports\",\n    icon: \"check\",\n  }),\n});"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_id","title","body"],"properties":{"user_id":{"type":"string"},"title":{"type":"string","maxLength":120},"body":{"type":"string","maxLength":500},"action_url":{"type":"string"},"icon":{"type":"string","enum":["check","warning","info","error"]}}}}}},"responses":{"201":{"description":"Notification queued"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Notifications"]}},"/v1/notifications/unread":{"get":{"operationId":"getUnreadNotifications","summary":"Poll for unread notifications for a user","description":"Returns unread notifications for a `user_id`. Poll this every 30 seconds from your frontend bell component.\n\nAuth: **Publishable key** — browser-safe.\n\nCORS: `Access-Control-Allow-Origin: *`. **Builder plan required.**","x-code-samples":[{"lang":"TypeScript","label":"Browser polling (publishable key)","source":"async function pollNotifications(userId: string) {\n  const res = await fetch(\n    `https://api.nordva.dev/v1/notifications/unread?user_id=${encodeURIComponent(userId)}`,\n    { headers: { \"Authorization\": \"Bearer nv_pub_live_YOUR_KEY\" } }\n  );\n  const { data, meta } = await res.json();\n  // data: unread notification array\n  // meta.unread_count: total unread\n  // meta.poll_interval_seconds: always 30, use this\n  return { notifications: data, unreadCount: meta.unread_count };\n}"}],"security":[{"PublishableApiKey":[]},{"SecretApiKey":[]}],"parameters":[{"name":"user_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Unread notifications with poll interval"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Notifications"]}},"/v1/notifications/{id}/read":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"operationId":"markNotificationRead","summary":"Mark a notification as read","description":"Marks a single notification as read. Call when the user clicks or dismisses the notification.\n\nAuth: **Publishable key** — browser-safe. **Builder plan required.**","x-code-samples":[{"lang":"TypeScript","label":"Browser (publishable key)","source":"await fetch(`https://api.nordva.dev/v1/notifications/${id}/read`, {\n  method: \"PATCH\",\n  headers: { \"Authorization\": \"Bearer nv_pub_live_YOUR_KEY\" },\n});"}],"security":[{"PublishableApiKey":[]},{"SecretApiKey":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Marked as read"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Notifications"]}},"/v1/auth/provision":{"post":{"operationId":"provisionAccount","summary":"Provision an account for a Clerk user","description":"Called by the dashboard on first sign-in. Idempotent. Creates an account, default project, and first API key if absent.\n\nAuth: Clerk JWT. API keys are explicitly rejected here.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Account already existed"},"201":{"description":"Account provisioned. Body includes the one-time `api_key`."},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/overview":{"get":{"operationId":"getDashboardOverview","summary":"Dashboard overview (metrics + recent activity)","description":"Returns usage counts and an activity-log feed for the calling user's project.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Overview payload"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/api-keys":{"get":{"operationId":"listApiKeys","summary":"List API keys (masked)","description":"Returns key prefix + masked tail. The plaintext key is only ever returned at creation.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Masked key list with `type` field (secret | publishable)"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]},"post":{"operationId":"createApiKey","summary":"Create a new API key","description":"Creates a secret or publishable API key. Returns the plaintext `api_key` exactly once — it cannot be retrieved again.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":80},"type":{"type":"string","enum":["secret","publishable"],"default":"secret"}}}}}},"responses":{"201":{"description":"Key created. Body includes plaintext `api_key` and `type`."},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"422":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/api-keys/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"operationId":"renameApiKey","summary":"Rename an API key","description":"Updates the display name of a key. Auth: Clerk JWT.","security":[{"ClerkJWT":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":80}}}}}},"responses":{"200":{"description":"Renamed"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]},"delete":{"operationId":"revokeApiKey","summary":"Revoke an API key","description":"Soft-revokes the key. Revocation is immediate — traffic using it starts failing instantly.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Revoked"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/billing/status":{"get":{"operationId":"getBillingStatus","summary":"Get current billing plan + subscription status","description":"Returns `{ plan, subscription_id, subscription_status }`. Checkout and the customer portal are hosted by Clerk client-side.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Plan + subscription status"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/billing/checkout":{"post":{"operationId":"createBillingCheckout","summary":"Start a Stripe Checkout Session","description":"Body `{ plan: 'indie' | 'builder', interval: 'monthly' | 'annual' }`. Returns `{ kind: 'checkout', url }` for a new subscription, or `{ kind: 'portal', url }` (a Customer Portal plan-change flow) when the account already has a subscription.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Redirect URL"},"400":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"503":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/v1/billing/portal":{"post":{"operationId":"createBillingPortal","summary":"Open the Stripe Customer Portal","description":"Returns `{ url }` for the Customer Portal (payment method, invoices, cancel). 404 `NO_BILLING_ACCOUNT` when the account has never checked out.\n\nAuth: Clerk JWT.","security":[{"ClerkJWT":[]}],"responses":{"200":{"description":"Portal URL"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"503":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Dashboard (Clerk session)"]}},"/webhooks/stripe":{"post":{"operationId":"handleStripeWebhook","summary":"Stripe webhook receiver","description":"Receives `checkout.session.completed`, `customer.subscription.created|updated|deleted`, `invoice.paid`, `invoice.payment_failed`. Verified with the `Stripe-Signature` header (HMAC-SHA256). Idempotent per event id. This handler is the only writer of the account plan.","security":[],"parameters":[{"name":"Stripe-Signature","in":"header","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Event handled (or duplicate ignored)"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"503":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Project"]}},"/v1/project":{"get":{"operationId":"getProject","summary":"Get the project's name and slug","description":"The slug is the public identifier in hosted page URLs.\n\nAuth: Secret key only.","responses":{"200":{"description":"Project name and slug"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Project"]},"patch":{"operationId":"updateProject","summary":"Rename the project or change its slug","description":"Slugs are unique across all projects. A slug can be changed twice in any 30 days; a slug you give up stays reserved for you for 30 days, and public links to it keep working until another project takes it.\n\nAuth: Secret key only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"slug":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,38}[a-z0-9]$|^[a-z0-9]$"}}}}}},"responses":{"200":{"description":"Updated"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"`SLUG_TAKEN`","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"422":{"description":"`INVALID_SLUG`","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"429":{"description":"`SLUG_CHANGE_LIMIT_REACHED`","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Project"]}},"/v1/waitlist/import":{"post":{"operationId":"importWaitlist","summary":"Import an existing list","description":"Bring signups over from another tool. At most 1,000 rows per call. Rows are validated one by one: a bad row is skipped and reported, it never fails the call. Nobody is emailed. Imports count toward the plan's signup limit, and running the same rows twice is safe. `created_at` keeps the original signup order.\n\nAuth: Secret key only. All plans.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rows","consent_confirmed"],"properties":{"rows":{"type":"array","minItems":1,"maxItems":1000,"items":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]}},"source":{"type":"object","properties":{"referrer":{"type":"string","maxLength":2048},"utm_source":{"type":"string","maxLength":255},"utm_medium":{"type":"string","maxLength":255},"utm_campaign":{"type":"string","maxLength":255},"landing_path":{"type":"string","maxLength":512}},"additionalProperties":false}},"required":["email"],"additionalProperties":false}},"consent_confirmed":{"type":"boolean","const":true,"description":"You confirm these people agreed to hear from you about this product."}}}}}},"responses":{"200":{"description":"`inserted`, `skipped`, `skipped_by_reason` (`invalid_row`, `duplicate_in_file`, `already_on_list`, `disposable_email`, `plan_limit_reached`), the first 100 `skipped_rows` with their index, and `remaining_capacity`."},"400":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/email-templates":{"get":{"operationId":"listWaitlistEmailTemplates","summary":"List the waitlist email templates","description":"The signup receipt and the invite email: current copy, Launch's default, the placeholders each accepts, and whether your copy is in use.\n\nAuth: Secret key only. All plans.","responses":{"200":{"description":"Templates"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/email-templates/{kind}":{"parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","enum":["waitlist_receipt","waitlist_invite"]}}],"put":{"operationId":"saveWaitlistEmailTemplate","summary":"Save your own copy for a waitlist email","description":"Plain text with `{{placeholders}}`, never HTML. Unknown placeholders are rejected by name, and the invite must include `{{invite_url}}`. The unsubscribe footer is added by Launch and is not part of the template.\n\nAuth: Secret key only. Builder plan.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subject","body"],"properties":{"subject":{"type":"string","maxLength":150},"body":{"type":"string","maxLength":5000}}}}}},"responses":{"200":{"description":"Saved"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"422":{"description":"`EMAIL_TEMPLATE_INVALID`. `param` is `subject` or `body`.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]},"delete":{"operationId":"resetWaitlistEmailTemplate","summary":"Go back to Launch's default email","description":"Auth: Secret key only.","responses":{"200":{"description":"Reset"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/waitlist/email-templates/{kind}/preview":{"parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","enum":["waitlist_receipt","waitlist_invite"]}}],"post":{"operationId":"previewWaitlistEmailTemplate","summary":"Render a template with sample values, without saving","description":"Returns `subject`, `html` and `text`.\n\nAuth: Secret key only. All plans.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subject","body"],"properties":{"subject":{"type":"string"},"body":{"type":"string"}}}}}},"responses":{"200":{"description":"Rendered email"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"422":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Waitlist"]}},"/v1/insights":{"get":{"operationId":"getInsights","summary":"What happened in a period, against the period before","description":"Counts from data Launch already stores: waitlist signups and top sources, changelog entries and new subscribers, feedback by classification with the latest summaries, notifications read rate, and revenue when Stripe is connected. There is no tracking script, so there are no pageviews.\n\nAuth: Secret key only. All plans.","parameters":[{"name":"period_days","in":"query","schema":{"type":"integer","minimum":1,"maximum":365,"default":30}}],"responses":{"200":{"description":"Insights"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Project"]}},"/v1/integrations/stripe":{"get":{"operationId":"getStripeConnectionStatus","summary":"Stripe connection status","description":"Whether your own Stripe account is connected (read-only), the sync status, the last sync time, how many customers, subscriptions and invoices are synced, and the last sync error. Connecting and disconnecting are only possible in the dashboard, behind your login: there is no API-key route for them, and the key is never returned.\n\nAuth: Secret key only.","responses":{"200":{"description":"Connection status"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Revenue"]}},"/v1/revenue/summary":{"get":{"operationId":"getRevenueSummary","summary":"MRR, subscriptions, new, churned and collected","description":"Per currency: `mrr_minor`, active and trialing subscriptions, paying customers, and for the period new and churned subscriptions with their MRR, net MRR change, collected revenue and payment count. MRR is operational: yearly plans ÷ 12, running coupons applied, metered and tiered prices counted as zero, refunds not subtracted. Amounts are in the smallest currency unit, reported per currency, and never converted or added together. Every response includes `sync` (`status`, `last_synced_at`, `livemode`): `backfilling` means the first import is still running, `revoked` or `error` means the numbers are as of the last successful sync.\n\nAuth: Secret key only. Indie or Builder.","parameters":[{"name":"period_days","in":"query","schema":{"type":"integer","minimum":1,"maximum":730,"default":30},"description":"Capped by plan: Indie 90, Builder 730."}],"responses":{"200":{"description":"Revenue summary"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"`STRIPE_NOT_CONNECTED`: connect Stripe in the dashboard first.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Revenue"]}},"/v1/revenue/series":{"get":{"operationId":"getRevenueSeries","summary":"Collected revenue over time","description":"Paid-invoice revenue per bucket, per currency, with empty buckets filled with zero. Up to 90 days is daily, up to a year is ISO weeks, beyond that monthly. A range longer than the plan's history is shortened and `clamped_to_plan` is true. Amounts are in the smallest currency unit, reported per currency, and never converted or added together. Every response includes `sync` (`status`, `last_synced_at`, `livemode`): `backfilling` means the first import is still running, `revoked` or `error` means the numbers are as of the last successful sync.\n\nAuth: Secret key only. Indie or Builder.","parameters":[{"name":"range","in":"query","schema":{"type":"string","enum":["30d","90d","12m","all"],"default":"30d"}}],"responses":{"200":{"description":"Revenue series"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"`STRIPE_NOT_CONNECTED`: connect Stripe in the dashboard first.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Revenue"]}},"/v1/revenue/events":{"get":{"operationId":"listRevenueEvents","summary":"Recent payments and cancellations","description":"Newest first, with the customer's email, name and plan. For a cancellation, `amount_minor` is the monthly amount that stopped, not a refund. Amounts are in the smallest currency unit, reported per currency, and never converted or added together. Every response includes `sync` (`status`, `last_synced_at`, `livemode`): `backfilling` means the first import is still running, `revoked` or `error` means the numbers are as of the last successful sync.\n\nAuth: Secret key only. Indie or Builder.","parameters":[{"name":"type","in":"query","schema":{"type":"string","enum":["payment","cancellation"]},"description":"Omit for both."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Events"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"409":{"description":"`STRIPE_NOT_CONNECTED`: connect Stripe in the dashboard first.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Revenue"]}},"/v1/contacts":{"get":{"operationId":"listContacts","summary":"List contacts","description":"One record per person across waitlist signups, changelog subscribers, feedback and your Stripe customers, matched on normalised email (lowercase, +alias removed, dots ignored on Gmail). Works without Stripe. Free plan: waitlist people only, one page of at most 100 (`meta.plan_limited`).\n\nAuth: Secret key only.","parameters":[{"name":"paying","in":"query","schema":{"type":"boolean"},"description":"Has an active or past-due subscription."},{"name":"has_feedback","in":"query","schema":{"type":"boolean"}},{"name":"status","in":"query","schema":{"type":"string","enum":["waiting","invited","unsubscribed"]},"description":"Waitlist status."},{"name":"source","in":"query","schema":{"type":"string"},"description":"A `utm_source` or referrer hostname, or `direct`, `referral`, `stripe`."},{"name":"stage","in":"query","schema":{"type":"string","enum":["potential","in_talks","customer","recurring","not_a_fit","inactive"]}},{"name":"q","in":"query","schema":{"type":"string"},"description":"Part of an email address."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"`meta.next_cursor` from the previous page."}],"responses":{"200":{"description":"Contacts, with `meta.next_cursor` and `meta.has_more`"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Contacts"]}},"/v1/contacts/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Contact id, e.g. `ct_9f2c…`. Ids belong to one project."}],"get":{"operationId":"getContact","summary":"Get one person across every primitive","description":"Adds the waitlist signup with its first-touch source, every subscription, lifetime paid per currency, the latest five feedback submissions, notifications sent and read, and the note.\n\nAuth: Secret key only.","responses":{"200":{"description":"Contact"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"`CONTACT_NOT_FOUND`","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Contacts"]},"patch":{"operationId":"updateContact","summary":"Set a contact's stage and note","description":"The only two fields Launch owns on a contact. Send `null` to clear either. A note replaces the previous one.\n\nAuth: Secret key only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stage":{"type":["string","null"],"enum":["potential","in_talks","customer","recurring","not_a_fit","inactive",null]},"note":{"type":["string","null"],"maxLength":5000}}}}}},"responses":{"200":{"description":"Updated contact"},"400":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"404":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Contacts"]}},"/v1/attribution":{"get":{"operationId":"getAttributionReport","summary":"Which signup sources produce paying customers","description":"Per source: signups, confirmed, invited, paying, ever paid, the signup-to-paying rate, and current MRR and collected revenue per currency. It only covers people who signed up through a Launch waitlist form, page or widget; it is not page analytics. Paying and money need a connected Stripe account and match on email; without one the funnel still works and paying is zero. Sources are recorded on every plan.\n\nAuth: Secret key only. Indie: `referrer`. Builder: all groupings.","parameters":[{"name":"group_by","in":"query","schema":{"type":"string","enum":["referrer","utm_source","utm_campaign","referral_code"],"default":"referrer"}},{"name":"period_days","in":"query","schema":{"type":"integer","minimum":1,"maximum":3650},"description":"Only signups from the last N days. Omit for all time."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"description":"Attribution report"},"401":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}},"403":{"description":"Error envelope. See `error.code` for the discriminator.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"null"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"remediation":{"type":"string"},"doc_url":{"type":"string","format":"uri"},"param":{"type":"string"},"request_id":{"type":"string"}},"required":["code","message","remediation"],"additionalProperties":false},"meta":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data","error"],"additionalProperties":false}}}}},"tags":["Attribution"]}}},"tags":[{"name":"Changelog"},{"name":"Waitlist"},{"name":"Feedback"},{"name":"Notifications"},{"name":"Revenue"},{"name":"Contacts"},{"name":"Attribution"},{"name":"Project"},{"name":"Dashboard (Clerk session)"}]}