{"openapi":"3.1.0","info":{"title":"rasket API","version":"1.0.0","description":"The rasket email API: transactional sends and broadcasts. Authenticate with `Authorization: Bearer rk_…` and send a User-Agent on every request. Every operation carries `x-rasket-permission` — the least credential that reaches it: `sending_access` or `full_access` for an API key, `session` for the dashboard cookie, `none` for an unauthenticated route, or `null` when no key or session reaches it (`/mcp` takes only an OAuth access token) — and `x-rasket-scope`, the OAuth scope a token needs, or `null` when no scope reaches it."},"servers":[{"url":"https://api.rasket.com","description":"production"},{"url":"https://www.rasket.com/api/v1","description":"this deployment"}],"tags":[{"name":"operations","description":"Liveness and readiness. Unauthenticated, outside the customer contract."},{"name":"auth","description":"The dashboard's own session: signup, login, logout, verification, password reset and MFA. Cookie-authenticated; not callable with an API key."},{"name":"teams","description":"The teams a signed-in user belongs to, switching between them, members and invitations. Session only."},{"name":"billing","description":"The team's plan, Checkout, the billing portal, invoices, pay-as-you-go and add-ons. A `full_access` API key or a session; an OAuth token may read with `billing:read` and never write."},{"name":"domains","description":"Sending domains: add one, publish its DNS records, verify, claim, rotate DKIM and auto-configure."},{"name":"api-keys","description":"Create, list, rename and revoke API keys."},{"name":"suppressions","description":"Addresses the team will not send to, and why — added by a bounce, a complaint or by hand."},{"name":"webhooks","description":"Webhook endpoints, their signing secrets, the events delivered to them, attempts and replay."},{"name":"logs","description":"Every request made with the team's credentials."},{"name":"templates","description":"Versioned email content with typed variables, addressed by id or alias."},{"name":"emails","description":"Send, batch, retrieve, list, reschedule and cancel emails; attachments, metrics and share links."},{"name":"receiving","description":"Mail sent to the team's receiving domains: the message, its attachments and its raw source."},{"name":"contact-properties","description":"The typed custom fields every contact in the team can carry."},{"name":"contacts","description":"The audience: contacts, CSV imports, their segment memberships and topic choices."},{"name":"segments","description":"Audiences defined by a filter, by hand, or both."},{"name":"topics","description":"What contacts subscribe to, and the list the preference page shows."},{"name":"broadcasts","description":"One message to a segment: the draft, the send gate, the send and the report."},{"name":"oauth","description":"The OAuth 2.1 authorization server: authorize, token, dynamic client registration, revocation and grants."},{"name":"automations","description":"Workflows that run per contact: the step graph, its versions, and every run."},{"name":"events","description":"Custom events: the names a product fires, and sending one to start an automation."},{"name":"mcp","description":"The remote Model Context Protocol server. Takes an OAuth access token and nothing else."},{"name":"team","description":"The team a credential belongs to: its profile, plan, sender identity, AI assist and single sign-on summary, and its members."},{"name":"ai","description":"AI assist: subject-line suggestions, drafting a body from a brief, and explaining what happened to an email. Needs AI assist turned on for the team; each accepted request spends one of the month's AI credits. A `full_access` API key, or an OAuth token with `ai:use`."}],"security":[{"bearerAuth":[]}],"components":{"schemas":{"CreateContactImportOptions":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"CSV file to import. Maximum size is 50MB."},"column_map":{"type":"string","description":"JSON-encoded object mapping contact fields and custom property keys to CSV column names. Supports `email`, `first_name`, `last_name`, `unsubscribed`, and `properties`. Custom property mappings can include `type` as `string`, `number`, or `boolean`; defaults to `string`.","example":"{\"email\":\"Email\",\"first_name\":\"First Name\",\"last_name\":\"Last Name\",\"unsubscribed\":\"Unsubscribed\",\"properties\":{\"plan\":{\"column\":\"Plan\",\"type\":\"string\"}}}"},"on_conflict":{"type":"string","enum":["upsert","skip"],"default":"skip","description":"Strategy to use when an imported contact already exists.","example":"skip"},"segments":{"type":"string","description":"JSON-encoded array of segments to add imported contacts to.","example":"[{\"id\":\"78261eea-8f8b-4381-83c6-79fa7120f1cf\"}]"},"topics":{"type":"string","description":"JSON-encoded array of topic subscriptions to apply to imported contacts. Each `subscription` must be `opt_in` or `opt_out`.","example":"[{\"id\":\"b6d24b8e-af0b-4c3c-be0c-359bbd97381e\",\"subscription\":\"opt_in\"}]"}},"required":["file"]},"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"version":{"type":"string"},"env":{"type":"string"}},"required":["status","version","env"],"additionalProperties":false},"Ready":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"]},"version":{"type":"string"},"env":{"type":"string"},"checks":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"ok":{"type":"boolean"},"durationMs":{"type":"number"},"error":{"type":"string"}},"required":["name","ok","durationMs"],"additionalProperties":false}},"failed":{"type":"array","items":{"type":"string"}}},"required":["status","version","env","checks","failed"],"additionalProperties":false},"Error":{"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string","enum":["invalid_idempotency_key","validation_error","missing_api_key","invalid_api_key","restricted_api_key","email_above_quota","invalid_permission","suspended_api_key","not_found","method_not_allowed","concurrent_idempotent_requests","invalid_idempotent_request","resource_locked","receiving_mx_in_use","invalid_attachment","invalid_parameter","missing_required_field","missing_required_parameter","daily_quota_exceeded","monthly_quota_exceeded","marketing_quota_exceeded","rate_limit_exceeded","application_error","not_implemented","service_unavailable"]},"message":{"type":"string"},"code":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"],"additionalProperties":false}},"claimable":{"type":"boolean"},"details":{"type":"object","properties":{"recipient":{"type":"string","description":"The first recipient the sandbox refused."},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"],"description":"The region that is still in our sending sandbox."},"allowed":{"type":"array","items":{"type":"string","enum":["verified_identity","verified_domain","simulator"]},"description":"Who the sandbox delivers to: verified identities, addresses on a domain verified in Rasket, and the mailbox simulator."},"next":{"type":"string","enum":["checkout"],"description":"The surface that would work instead. `checkout` means the team has no subscription to put an add-on on and should start one with POST /billing/checkout."},"reason":{"type":"string","enum":["return_path_in_use"],"description":"Why a domain's `custom_return_path` was refused: `return_path_in_use` means another service already publishes records at that label."},"label":{"type":"string","description":"The `custom_return_path` label that was refused."},"found":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"string"}},"required":["type","value"],"additionalProperties":false,"description":"The record that resolves at that label today."},"suggestion":{"type":"string","description":"A label that was free at the domain when we checked."}},"additionalProperties":false,"description":"On the 403 validation_error a send gets while its region is still in our sending sandbox (GET /team lists those regions in sending.sandbox_regions), on the 422 an add-on purchase gets when the team has no subscription, and on the 422 invalid_parameter a domain gets when its `custom_return_path` is already another service's."}},"required":["statusCode","name","message"],"additionalProperties":false},"Session":{"type":"object","properties":{"object":{"type":"string","enum":["session"]},"user":{"$ref":"#/components/schemas/User"},"current_team":{"$ref":"#/components/schemas/Team"}},"required":["object","user","current_team"],"additionalProperties":false},"User":{"type":"object","properties":{"object":{"type":"string","enum":["user"]},"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":["string","null"]},"email_verified_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["object","id","email","name","email_verified_at","created_at"],"additionalProperties":false},"Team":{"type":["object","null"],"properties":{"object":{"type":"string","enum":["team"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"risk_state":{"type":"string"},"created_at":{"type":"string"}},"required":["object","id","name","slug","risk_state","created_at"],"additionalProperties":false},"SignupRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"password":{"type":"string","minLength":6,"maxLength":4096},"name":{"type":"string","maxLength":200}},"required":["email","password"]},"MfaChallenge":{"type":"object","properties":{"object":{"type":"string","enum":["mfa_challenge"]},"challenge_token":{"type":"string"},"expires_at":{"type":"string"}},"required":["object","challenge_token","expires_at"],"additionalProperties":false},"LoginRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"password":{"type":"string","minLength":1,"maxLength":4096}},"required":["email","password"]},"LogoutResult":{"type":"object","properties":{"object":{"type":"string","enum":["session"]},"revoked":{"type":"boolean","enum":[true]}},"required":["object","revoked"],"additionalProperties":false},"LogoutRequest":{"type":"object","properties":{"all":{"type":"boolean"}}},"VerifyEmailResult":{"type":"object","properties":{"object":{"type":"string","enum":["user"]},"id":{"type":"string","format":"uuid"},"email_verified_at":{"type":["string","null"]}},"required":["object","id","email_verified_at"],"additionalProperties":false},"TokenRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"maxLength":512}},"required":["token"]},"PasswordResetRequested":{"type":"object","properties":{"object":{"type":"string","enum":["password_reset"]},"requested":{"type":"boolean","enum":[true]}},"required":["object","requested"],"additionalProperties":false},"EmailRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320}},"required":["email"]},"PasswordResetResult":{"type":"object","properties":{"object":{"type":"string","enum":["user"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"ResetPasswordRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"maxLength":512},"password":{"type":"string","minLength":6,"maxLength":4096}},"required":["token","password"]},"MfaStatus":{"type":"object","properties":{"object":{"type":"string","enum":["mfa"]},"enabled":{"type":"boolean"},"enabled_at":{"type":["string","null"]},"enrolling":{"type":"boolean"},"recovery_codes_remaining":{"type":"integer"},"has_password":{"type":"boolean"}},"required":["object","enabled","enabled_at","enrolling","recovery_codes_remaining","has_password"],"additionalProperties":false},"MfaEnrolment":{"type":"object","properties":{"object":{"type":"string","enum":["mfa_enrolment"]},"otpauth_url":{"type":"string"},"secret":{"type":"string"}},"required":["object","otpauth_url","secret"],"additionalProperties":false},"MfaActivated":{"type":"object","properties":{"object":{"type":"string","enum":["mfa"]},"enabled":{"type":"boolean","enum":[true]},"enabled_at":{"type":"string"},"recovery_codes":{"type":"array","items":{"type":"string"}}},"required":["object","enabled","enabled_at","recovery_codes"],"additionalProperties":false},"MfaConfirmRequest":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":64},"password":{"type":"string","maxLength":4096}},"required":["code"]},"MfaDisabled":{"type":"object","properties":{"object":{"type":"string","enum":["mfa"]},"enabled":{"type":"boolean","enum":[false]},"enabled_at":{"type":"null"}},"required":["object","enabled","enabled_at"],"additionalProperties":false},"MfaRecoveryCodes":{"type":"object","properties":{"object":{"type":"string","enum":["mfa_recovery_codes"]},"recovery_codes":{"type":"array","items":{"type":"string"}}},"required":["object","recovery_codes"],"additionalProperties":false},"MfaCodeRequest":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":64}},"required":["code"]},"MfaVerifyRequest":{"type":"object","properties":{"challenge_token":{"type":"string","minLength":1,"maxLength":512},"code":{"type":"string","minLength":1,"maxLength":64}},"required":["challenge_token","code"]},"MfaRecoveryRequest":{"type":"object","properties":{"challenge_token":{"type":"string","minLength":1,"maxLength":512},"recovery_code":{"type":"string","minLength":1,"maxLength":64}},"required":["challenge_token","recovery_code"]},"Me":{"type":"object","properties":{"object":{"type":"string","enum":["user"]},"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":["string","null"]},"email_verified_at":{"type":["string","null"]},"current_team_id":{"type":["string","null"],"format":"uuid"},"teams":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}},"required":["object","id","email","name","email_verified_at","current_team_id","teams"],"additionalProperties":false},"CreateTeamRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"]},"TeamList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}},"required":["object","has_more","data"],"additionalProperties":false},"TeamMemberList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}}},"required":["object","has_more","data"],"additionalProperties":false},"TeamMember":{"type":"object","properties":{"object":{"type":"string","enum":["team_member"]},"id":{"type":"string","format":"uuid"},"user_id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":["string","null"]},"role":{"type":"string"},"mfa_enabled":{"type":"boolean"},"sso_exempt":{"type":"boolean"},"created_at":{"type":"string"}},"required":["object","id","user_id","email","name","role","mfa_enabled","sso_exempt","created_at"],"additionalProperties":false},"SetTeamMemberRoleRequest":{"type":"object","properties":{"role":{"type":"string","enum":["admin","member","viewer"]}},"required":["role"]},"TeamInvitationList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamInvitation"}}},"required":["object","has_more","data"],"additionalProperties":false},"TeamInvitation":{"type":"object","properties":{"object":{"type":"string","enum":["team_invitation"]},"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member","viewer"]},"invited_by":{"type":["string","null"]},"expires_at":{"type":"string"},"created_at":{"type":"string"}},"required":["object","id","email","role","invited_by","expires_at","created_at"],"additionalProperties":false},"CreateTeamInvitationRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320},"role":{"type":"string","enum":["admin","member","viewer"]}},"required":["email","role"]},"TeamDeletion":{"type":"object","properties":{"object":{"type":"string","enum":["team_deletion"]},"team_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["none","scheduled","in_progress"],"description":"`none`: nothing is scheduled. `scheduled`: inside the grace window; sending is stopped and the deletion can still be canceled. `in_progress`: the purge has started and can no longer be canceled."},"requested_at":{"type":["string","null"]},"purge_after":{"type":["string","null"],"description":"When the project's data is erased: 30 days after the request, by the nightly retention job."},"requested_by":{"type":["string","null"],"format":"uuid"}},"required":["object","team_id","status","requested_at","purge_after","requested_by"],"additionalProperties":false},"TeamDeletionRequest":{"type":"object","properties":{"confirm":{"type":"string","maxLength":200,"description":"The project's name, typed exactly, to confirm the deletion.","example":"Acme"}},"required":["confirm"],"additionalProperties":false},"TeamExportList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamExport"}}},"required":["object","has_more","data"],"additionalProperties":false},"TeamExport":{"type":"object","properties":{"object":{"type":"string","enum":["team_export"]},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","running","completed","failed","expired"]},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]},"expires_at":{"type":["string","null"],"description":"When the archive is deleted and its link stops working: 7 days after it is ready."},"bytes":{"type":["integer","null"]},"truncated":{"type":"boolean","description":"True when a size or time ceiling was reached; `manifest.json` names what was left out."},"download_url":{"type":["string","null"],"description":"A signed dashboard link to the archive, for an admin signed in to the project, while the export is ready and unexpired."}},"required":["object","id","status","created_at","completed_at","expires_at","bytes","truncated","download_url"],"additionalProperties":false},"AcceptTeamInvitationRequest":{"type":"object","properties":{"token":{"type":"string","minLength":1,"maxLength":256}},"required":["token"]},"Billing":{"type":"object","properties":{"object":{"type":"string","enum":["billing"]},"plan":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"monthly_price_cents":{"type":"integer"},"included_emails":{"type":"integer"},"overage_per_1000_cents":{"type":["integer","null"]}},"required":["code","name","monthly_price_cents","included_emails","overage_per_1000_cents"],"additionalProperties":false},"effective_plan_code":{"type":"string"},"subscription":{"type":["object","null"],"properties":{"status":{"type":"string"},"current_period_start":{"type":"string"},"current_period_end":{"type":"string"},"invoicing":{"type":"string"},"latest_invoice_status":{"type":["string","null"]},"trial_ends_at":{"type":["string","null"],"description":"When the free trial ends, or `null` when no trial is running. Present only while `status` is `trialing`; a trial that has converted reports `null`."}},"required":["status","current_period_start","current_period_end","invoicing","latest_invoice_status","trial_ends_at"],"additionalProperties":false},"usage":{"type":"object","properties":{"period_start":{"type":"string"},"period_end":{"type":"string"},"emails":{"type":"integer"},"included_emails":{"type":"integer"},"emails_today":{"type":"integer","description":"Emails sent today, counted against `daily_limit`."},"day_start":{"type":"string","description":"Today as `YYYY-MM-DD` in UTC. `emails_today` starts again at 00:00 UTC."},"daily_limit":{"type":["integer","null"],"description":"The most this team can send today. `null` when there is no daily limit."},"monthly_limit":{"type":["integer","null"],"description":"The most this team can send this month before a send is refused: a limit set for the team, or the lower of the plan's allowance and the sending tier's cap. It can differ from `included_emails`, which is the plan's allowance and the line past which overage is billed. `null` when nothing caps the month."},"marketing_emails":{"type":"integer","description":"Broadcast recipients accepted this month. Its own pool: a broadcast never counts against `emails`, and `POST /emails` never counts against this."},"marketing_included_emails":{"type":"integer","description":"Marketing recipients this team may send each month: its marketing add-on's allowance, or the plan's own when it holds none."},"marketing_contacts_included":{"type":"integer","description":"Contacts this team may hold: its marketing add-on's allowance, or the plan's own when it holds none. Adding a contact past it is refused."},"marketing_addon_code":{"type":["string","null"],"description":"The marketing add-on granting `marketing_contacts_included` (`marketing_5k` … `marketing_150k`), or `null` when the plan's own allowance applies."}},"required":["period_start","period_end","emails","included_emails","emails_today","day_start","daily_limit","monthly_limit","marketing_emails","marketing_included_emails","marketing_contacts_included","marketing_addon_code"],"additionalProperties":false},"pay_as_you_go":{"type":"object","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"additionalProperties":false},"payment_method":{"type":"object","properties":{"present":{"type":"boolean"},"brand":{"type":["string","null"]},"last4":{"type":["string","null"]}},"required":["present","brand","last4"],"additionalProperties":false},"addons":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"quantity":{"type":"integer"},"status":{"type":"string"}},"required":["code","quantity","status"],"additionalProperties":false}},"inbox_seats":{"type":"object","properties":{"code":{"type":"string"},"quantity":{"type":"integer","description":"Seats billed: the team's open mailboxes minus `included`, floored at zero. Derived from the mailboxes, never set directly."},"included":{"type":"integer","description":"Mailboxes this team gets at no charge. It is set by the plan the team is on, and it counts channels and personal mailboxes alike. Extra addresses on a mailbox are free and are never counted."}},"required":["code","quantity","included"],"additionalProperties":false,"description":"Inbox seats. Every mailbox is a seat; a number of them are included on every plan and each one past that is billed. Always present, with `quantity` 0 when the team has no extra seats."},"pending_change":{"type":["object","null"],"properties":{"plan_code":{"type":"string"},"plan_name":{"type":"string"},"effective_at":{"type":"string"}},"required":["plan_code","plan_name","effective_at"],"additionalProperties":false},"payment_state":{"type":["object","null"],"properties":{"kind":{"type":"string","enum":["payment_failed"]},"invoice_url":{"type":["string","null"],"description":"A hosted page where the open invoice can be paid, when there is one."},"next_attempt_at":{"type":["string","null"],"description":"When the payment will be attempted again. `null` when no further attempt is scheduled."},"limits_end_at":{"type":"string","description":"When this plan's limits stop applying if the payment has not gone through by then. Until this moment `effective_plan_code` is still the paid plan."},"limits_reduced":{"type":"boolean","description":"True once the limits have already dropped to the free plan's, which is when `effective_plan_code` is `free`."}},"required":["kind","invoice_url","next_attempt_at","limits_end_at","limits_reduced"],"additionalProperties":false,"description":"Set when a payment for this subscription has failed and has not yet been settled. `null` when nothing is outstanding."},"checkout_available":{"type":"boolean"},"paid_plan":{"type":"boolean","description":"True when the team is on a paid plan. Not the same as `!checkout_available`: a team that bought inbox storage on its own has a subscription while still on the free plan."},"storage_addon_purchase":{"type":"string","enum":["add_item","checkout","held","unavailable"],"description":"How to buy inbox storage right now. `add_item` is `POST /billing/addons` on the subscription the team already has, `checkout` is `POST /billing/checkout` with `addon_code`, `held` means the team already has it, and `unavailable` means it cannot be bought at the moment — both surfaces answer `503 service_unavailable` until it can."},"dedicated_ip":{"type":"object","properties":{"recommended_min_daily":{"type":"integer","description":"The daily send volume a dedicated IP is recommended from. A recommendation, never a gate: any team on Scale or above can buy one whatever this says.","example":5000},"avg_daily_sends_30d":{"type":"integer","description":"This team's own average daily sends over the last 30 whole UTC days, to compare against `recommended_min_daily`. Today is not counted, because a partial day would drag it down all morning.","example":1200}},"required":["recommended_min_daily","avg_daily_sends_30d"],"additionalProperties":false,"description":"What a dedicated IP is recommended from, and what this team actually sends. Shown side by side so the choice is yours."}},"required":["object","plan","effective_plan_code","subscription","usage","pay_as_you_go","payment_method","addons","inbox_seats","pending_change","payment_state","checkout_available","paid_plan","storage_addon_purchase","dedicated_ip"],"additionalProperties":false},"CheckoutSession":{"type":"object","properties":{"object":{"type":"string","enum":["checkout_session"]},"url":{"type":"string","format":"uri"},"expires_at":{"type":"string"}},"required":["object","url","expires_at"],"additionalProperties":false},"PortalSession":{"type":"object","properties":{"object":{"type":"string","enum":["portal_session"]},"url":{"type":"string","format":"uri"}},"required":["object","url"],"additionalProperties":false},"BillingInvoiceList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/BillingInvoice"}}},"required":["object","has_more","data"],"additionalProperties":false},"BillingInvoice":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":["string","null"]},"status":{"type":"string"},"total_cents":{"type":"integer"},"currency":{"type":"string"},"created_at":{"type":"string"},"hosted_invoice_url":{"type":["string","null"]},"invoice_pdf":{"type":["string","null"]}},"required":["id","number","status","total_cents","currency","created_at","hosted_invoice_url","invoice_pdf"],"additionalProperties":false},"CreateDomainResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","not_started","partially_verified","partially_failed"]},"capabilities":{"$ref":"#/components/schemas/DomainCapabilities"},"managed":{"type":"boolean","description":"True for your team's managed address, `<word>.<managed host>` (a Rasket extension). It exists from the moment your team does and we verify it for you, so it publishes no DNS records — and it can only reach the verified addresses of people on your team. Add a domain of your own to send anywhere else. Every write against a managed domain is `422 validation_error`.","example":false},"records":{"type":"array","items":{"$ref":"#/components/schemas/DomainRecord"}},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"]},"open_tracking":{"type":"boolean"},"click_tracking":{"type":"boolean"},"tracking_subdomain":{"type":"string"},"receiving_host":{"type":"string","description":"Where the domain receives mail (a Rasket extension): `@` by default, so mail arrives at `anything@<name>`; or a DNS label such as `inbound` for `anything@inbound.<name>`. An MX at `@` takes the domain's mail from whichever mailbox provider has it today.","example":"@"},"custom_return_path":{"type":"string","description":"The label the Sending records are published at (a Rasket extension). Chosen free at creation when you name none, and changeable with PATCH.","example":"rasket"}},"required":["id","name","created_at","status","capabilities","managed","records","region","open_tracking","click_tracking","tracking_subdomain","receiving_host","custom_return_path"],"additionalProperties":false},"DomainCapabilities":{"type":"object","properties":{"sending":{"type":"string","enum":["enabled","disabled"]},"receiving":{"type":"string","enum":["enabled","disabled"]}},"required":["sending","receiving"],"additionalProperties":false},"DomainRecord":{"type":"object","properties":{"record":{"type":"string","enum":["SPF","DKIM","Receiving","Tracking","TrackingCAA","BIMI"]},"name":{"type":"string"},"type":{"type":"string","enum":["MX","TXT","CNAME","CAA"]},"ttl":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","temporary_failure","not_started"]},"value":{"type":"string"},"priority":{"type":"integer"}},"required":["record","name","type","ttl","status","value"],"additionalProperties":false},"DomainList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListDomainsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListDomainsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","not_started","partially_verified","partially_failed"]},"created_at":{"type":"string"},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"]},"open_tracking":{"type":"boolean"},"click_tracking":{"type":"boolean"},"capabilities":{"$ref":"#/components/schemas/DomainCapabilities"},"managed":{"type":"boolean","description":"True for your team's managed address, `<word>.<managed host>` (a Rasket extension). It exists from the moment your team does and we verify it for you, so it publishes no DNS records — and it can only reach the verified addresses of people on your team. Add a domain of your own to send anywhere else. Every write against a managed domain is `422 validation_error`.","example":false}},"required":["id","name","status","created_at","region","open_tracking","click_tracking","capabilities","managed"],"additionalProperties":false},"DomainClaim":{"type":"object","properties":{"object":{"type":"string","enum":["domain_claim"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","verified","completed","blocked","expired","superseded","canceled","failed"]},"domain_id":{"type":["string","null"],"format":"uuid"},"region":{"type":["string","null"],"enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1",null]},"record":{"$ref":"#/components/schemas/DomainClaimRecord"},"blocked_reason":{"type":["string","null"],"enum":["grace_period","recent_owner_activity","pending_scheduled_emails",null]},"failure_reason":{"type":["string","null"]},"created_at":{"type":"string"},"expires_at":{"type":"string"}},"required":["object","id","name","status","domain_id","region","record","blocked_reason","failure_reason","created_at","expires_at"],"additionalProperties":false},"DomainClaimRecord":{"type":"object","properties":{"record":{"type":"string","enum":["Claim"]},"name":{"type":"string"},"type":{"type":"string","enum":["TXT"]},"ttl":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","temporary_failure","not_started"]},"value":{"type":"string"}},"required":["record","name","type","ttl","status","value"],"additionalProperties":false},"Domain":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","not_started","partially_verified","partially_failed"]},"created_at":{"type":"string"},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"]},"open_tracking":{"type":"boolean"},"click_tracking":{"type":"boolean"},"tracking_subdomain":{"type":"string"},"receiving_host":{"type":"string","description":"Where the domain receives mail (a Rasket extension): `@` by default, so mail arrives at `anything@<name>`; or a DNS label such as `inbound` for `anything@inbound.<name>`. An MX at `@` takes the domain's mail from whichever mailbox provider has it today.","example":"@"},"custom_return_path":{"type":"string","description":"The label the Sending records are published at (a Rasket extension). Chosen free at creation when you name none, and changeable with PATCH.","example":"rasket"},"capabilities":{"$ref":"#/components/schemas/DomainCapabilities"},"managed":{"type":"boolean","description":"True for your team's managed address, `<word>.<managed host>` (a Rasket extension). It exists from the moment your team does and we verify it for you, so it publishes no DNS records — and it can only reach the verified addresses of people on your team. Add a domain of your own to send anywhere else. Every write against a managed domain is `422 validation_error`.","example":false},"records":{"type":"array","items":{"$ref":"#/components/schemas/DomainRecord"}}},"required":["object","id","name","status","created_at","region","open_tracking","click_tracking","tracking_subdomain","receiving_host","custom_return_path","capabilities","managed","records"],"additionalProperties":false},"DomainRef":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"DeleteDomainResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"VerifyDomainResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["pending","verified","failed","not_started","partially_verified","partially_failed"]},"created_at":{"type":"string"},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"]},"open_tracking":{"type":"boolean"},"click_tracking":{"type":"boolean"},"tracking_subdomain":{"type":"string"},"receiving_host":{"type":"string","description":"Where the domain receives mail (a Rasket extension): `@` by default, so mail arrives at `anything@<name>`; or a DNS label such as `inbound` for `anything@inbound.<name>`. An MX at `@` takes the domain's mail from whichever mailbox provider has it today.","example":"@"},"custom_return_path":{"type":"string","description":"The label the Sending records are published at (a Rasket extension). Chosen free at creation when you name none, and changeable with PATCH.","example":"rasket"},"capabilities":{"$ref":"#/components/schemas/DomainCapabilities"},"managed":{"type":"boolean","description":"True for your team's managed address, `<word>.<managed host>` (a Rasket extension). It exists from the moment your team does and we verify it for you, so it publishes no DNS records — and it can only reach the verified addresses of people on your team. Add a domain of your own to send anywhere else. Every write against a managed domain is `422 validation_error`.","example":false},"records":{"type":"array","items":{"$ref":"#/components/schemas/DomainRecord"}}},"required":["object","id","name","status","created_at","region","open_tracking","click_tracking","tracking_subdomain","receiving_host","custom_return_path","capabilities","managed","records"],"additionalProperties":false},"AutoconfigureResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"},"created":{"type":"array","items":{"type":"string"}},"updated":{"type":"array","items":{"type":"string"}},"conflicts":{"type":"array","items":{"type":"string"}},"credential_kept":{"type":"boolean"}},"required":["object","id","created","updated","conflicts","credential_kept"],"additionalProperties":false},"DeleteCredentialResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"DomainBrandLogo":{"type":"object","properties":{"object":{"type":"string","enum":["domain_brand_logo"]},"domain_id":{"type":"string","format":"uuid"},"url":{"type":"string","description":"The stable HTTPS URL the logo is served at — the `l=` tag's value.","example":"https://share.rasket.com/bimi/0198f0a1-0000-7000-8000-000000000000/9d3c5d18b976973c1b6e4bcc0d7d3dfc76db4a69ccdb9aaebbc78e919d623909.svg"},"bytes":{"type":"integer","description":"Size of the hosted SVG."},"sha256":{"type":"string","description":"SHA-256 of the hosted bytes, 64 lowercase hex characters."},"uploaded_at":{"type":"string"}},"required":["object","domain_id","url","bytes","sha256","uploaded_at"],"additionalProperties":false},"DeleteDomainBrandLogoResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain_brand_logo"]},"domain_id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","domain_id","deleted"],"additionalProperties":false},"DomainBrandCertificate":{"type":"object","properties":{"object":{"type":"string","enum":["domain_brand_certificate"]},"domain_id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["none","awaiting_certificate","active","logo_changed","expired"],"description":"Where the certificate has got to. `logo_changed` means the logo was replaced after the certificate was issued, so the two no longer match; `expired` means it is past its end date. Neither is published, and neither throws anything away."},"csr_pem":{"type":["string","null"],"description":"The certificate signing request, PEM, or null before one is made."},"subject":{"$ref":"#/components/schemas/DomainBrandCertificateSubject"},"requested_at":{"type":["string","null"]},"url":{"type":["string","null"],"description":"The stable HTTPS URL the issued chain is served at — the `a=` tag's value.","example":"https://share.rasket.com/bimi/0198f0a1-0000-7000-8000-000000000000/9d3c5d18b976973c1b6e4bcc0d7d3dfc76db4a69ccdb9aaebbc78e919d623909.pem"},"bytes":{"type":["integer","null"]},"sha256":{"type":["string","null"],"description":"SHA-256 of the hosted chain, 64 lowercase hex characters."},"issuer":{"type":["string","null"],"description":"The issuing authority's common name.","example":"DigiCert Inc"},"expires_at":{"type":["string","null"]},"installed_at":{"type":["string","null"]},"published":{"type":"boolean","description":"True only while `state` is `active`, which is when `default._bimi` carries `a=`."},"reason":{"type":["string","null"],"description":"One sentence naming what to do next, or null when nothing."}},"required":["object","domain_id","state","csr_pem","subject","requested_at","url","bytes","sha256","issuer","expires_at","installed_at","published","reason"],"additionalProperties":false},"DomainBrandCertificateSubject":{"type":["object","null"],"properties":{"common_name":{"type":"string"},"organization":{"type":"string"},"organizational_unit":{"type":["string","null"]},"locality":{"type":"string"},"state":{"type":"string"},"country":{"type":"string"}},"required":["common_name","organization","organizational_unit","locality","state","country"],"additionalProperties":false},"DeleteDomainBrandCertificateResponse":{"type":"object","properties":{"object":{"type":"string","enum":["domain_brand_certificate"]},"domain_id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","domain_id","deleted"],"additionalProperties":false},"CreateApiKeyResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"token":{"type":"string"}},"required":["id","token"],"additionalProperties":false},"ApiKeyList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}},"required":["object","has_more","data"],"additionalProperties":false},"ApiKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string"},"last_used_at":{"type":["string","null"]},"permission":{"type":"string","enum":["full_access","sending_access"]},"domain_id":{"type":["string","null"],"format":"uuid"},"key_prefix":{"type":"string"},"status":{"type":"string","enum":["active","revoked","suspended"]},"last_used_request_log_id":{"type":["string","null"],"format":"uuid"}},"required":["id","name","created_at","last_used_at","permission","domain_id","key_prefix","status","last_used_request_log_id"],"additionalProperties":false},"UpdateApiKeyResponse":{"type":"object","properties":{"object":{"type":"string","enum":["api_key"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"DeleteApiKeyResponse":{"type":"object","properties":{"object":{"type":"string","enum":["api_key"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"CreatedSuppressionList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CreatedSuppression"}}},"required":["data"],"additionalProperties":false},"CreatedSuppression":{"type":"object","properties":{"object":{"type":"string","enum":["suppression"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"BatchAddSuppressionsRequest":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100,"example":["ronald.williams@example.com"]}},"required":["emails"]},"RemovedSuppressionList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RemovedSuppression"}}},"required":["data"],"additionalProperties":false},"RemovedSuppression":{"type":"object","properties":{"object":{"type":"string","enum":["suppression"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean"}},"required":["object","deleted"],"additionalProperties":false},"BatchRemoveSuppressionsRequest":{"type":"object","properties":{"emails":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100},"ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100,"example":["e169aa45-1ecf-4183-9955-b1499d5701d3"]}}},"CreateSuppressionRequest":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320,"example":"ronald.williams@example.com"}},"required":["email"]},"SuppressionList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/SuppressionListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"SuppressionListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"origin":{"type":"string","enum":["bounce","complaint","manual","unsubscribe"]},"source_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["id","email","origin","source_id","created_at"],"additionalProperties":false},"Suppression":{"type":"object","properties":{"object":{"type":"string","enum":["suppression"]},"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"origin":{"type":"string","enum":["bounce","complaint","manual","unsubscribe"]},"source_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":"string"}},"required":["object","id","email","origin","source_id","created_at"],"additionalProperties":false},"WebhookSecret":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string","format":"uuid"},"signing_secret":{"type":"string","example":"whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"}},"required":["object","id","signing_secret"],"additionalProperties":false},"WebhookList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"WebhookListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"endpoint":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]}},"status":{"type":"string","enum":["enabled","disabled"]},"created_at":{"type":"string"}},"required":["id","endpoint","events","status","created_at"],"additionalProperties":false},"WebhookEventRef":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_event"]},"id":{"type":"string"}},"required":["object","id"],"additionalProperties":false},"WebhookAttemptList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookAttempt"}}},"required":["object","has_more","data"],"additionalProperties":false},"WebhookAttempt":{"type":"object","properties":{"id":{"type":"string","example":"atmpt_0198f4c1000070008000000000000000"},"attempt_number":{"type":"integer"},"http_status_code":{"type":["integer","null"]},"response":{"type":["string","null"]},"duration_ms":{"type":"integer"},"error":{"type":["string","null"]},"sent_at":{"type":"string"}},"required":["id","attempt_number","http_status_code","response","duration_ms","error","sent_at"],"additionalProperties":false},"WebhookEvent":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_event"]},"id":{"type":"string","example":"msg_0198f4c1000070008000000000000000"},"type":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]},"created_at":{"type":"string"},"status":{"type":"string","enum":["pending","attempting","success","failed"]},"attempt_count":{"type":"integer"},"next_attempt_at":{"type":["string","null"]},"last_http_status":{"type":["integer","null"]},"payload":{}},"required":["object","id","type","created_at","status","attempt_count","next_attempt_at","last_http_status"],"additionalProperties":false},"WebhookEventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"WebhookEventListItem":{"type":"object","properties":{"id":{"type":"string","example":"msg_0198f4c1000070008000000000000000"},"type":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]},"created_at":{"type":"string"},"status":{"type":"string","enum":["pending","attempting","success","failed"]}},"required":["id","type","created_at","status"],"additionalProperties":false},"ParkedDelivery":{"type":"object","properties":{"object":{"type":"string","enum":["parked_delivery"]},"delivered":{"type":"integer"},"remaining":{"type":"integer","description":"Events still parked on the endpoint once this call returned."},"stopped_reason":{"type":["string","null"],"enum":["rate_limit_exceeded",null]}},"required":["object","delivered","remaining","stopped_reason"],"additionalProperties":false},"ParkedWebhookEventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ParkedWebhookEvent"}}},"required":["object","has_more","data"],"additionalProperties":false},"ParkedWebhookEvent":{"type":"object","properties":{"id":{"type":"string","example":"msg_0198f4c1000070008000000000000000"},"type":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]},"created_at":{"type":"string"},"status":{"type":"string","enum":["pending","attempting","success","failed"]},"attempt_count":{"type":"integer"},"last_http_status":{"type":["integer","null"]}},"required":["id","type","created_at","status","attempt_count","last_http_status"],"additionalProperties":false},"WebhookDetail":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string","format":"uuid"},"endpoint":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]}},"status":{"type":"string","enum":["enabled","disabled"]},"created_at":{"type":"string"},"signing_secret":{"type":"string","example":"whsec_••••••••LaSw"}},"required":["object","id","endpoint","events","status","created_at","signing_secret"],"additionalProperties":false},"WebhookRef":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"DeleteWebhookResponse":{"type":"object","properties":{"object":{"type":"string","enum":["webhook"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"LogList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/LogSummary"}}},"required":["object","has_more","data"],"additionalProperties":false},"LogSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"created_at":{"type":"string"},"endpoint":{"type":"string"},"method":{"type":"string"},"response_status":{"type":"integer"},"user_agent":{"type":["string","null"]},"source":{"type":"string"},"request_id":{"type":"string"},"latency_ms":{"type":"integer"},"api_key_id":{"type":["string","null"],"format":"uuid"}},"required":["id","created_at","endpoint","method","response_status","user_agent","source","request_id","latency_ms","api_key_id"],"additionalProperties":false},"Log":{"type":"object","properties":{"object":{"type":"string","enum":["log"]},"id":{"type":"string","format":"uuid"},"created_at":{"type":"string"},"endpoint":{"type":"string"},"method":{"type":"string"},"response_status":{"type":"integer"},"user_agent":{"type":["string","null"]},"source":{"type":"string"},"request_id":{"type":"string"},"latency_ms":{"type":"integer"},"api_key_id":{"type":["string","null"],"format":"uuid"},"request_body":{},"response_body":{},"email_id":{"type":["string","null"],"format":"uuid"}},"required":["object","id","created_at","endpoint","method","response_status","user_agent","source","request_id","latency_ms","api_key_id","email_id"],"additionalProperties":false},"CreateTemplateResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"object":{"type":"string","enum":["template"]}},"required":["id","object"],"additionalProperties":false},"CreateTemplateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Welcome","description":"The name of the template."},"alias":{"type":"string","example":"welcome","description":"A short name to address the template by instead of its ID: `^[a-z0-9][a-z0-9-_]{0,62}$`, lower-cased, never a UUID."},"from":{"type":"string","example":"Acme <hello@acme.com>","description":"Sender email address. To include a friendly name, use the format \"Your Name <sender@domain.com>\"."},"subject":{"type":"string","example":"Welcome, {{name}}","description":"Email subject. May carry `{{key}}` placeholders."},"reply_to":{"type":"array","items":{"type":"string"},"description":"Reply-to email addresses."},"html":{"type":"string","example":"<p>Hello {{name}}</p>","description":"The HTML version of the template. May carry `{{key}}` placeholders."},"text":{"type":"string","example":"Hello {{name}}","description":"The plain text version of the template. May carry `{{key}}` placeholders."},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariableInput"},"description":"The variables the bodies use. Every `{{key}}` must be declared here, and every declared key must be used."},"starter":{"type":"string","enum":["welcome-minimal","welcome","password-reset-card","magic-link","password-reset","sunny-promo","storefront","gift-card","editorial-launch","glow-offer","newsletter","order-confirmation","shipping","receipt","invoice"],"example":"receipt","description":"Start from a starter template instead of writing a body: its subject, HTML, plain text and variables become version 1. Send this **or** `html`, never both. `subject`, `text` and `variables` sent beside it override the starter's."},"brand_overrides":{"$ref":"#/components/schemas/TemplateBrandOverrides"}},"required":["name"]},"TemplateVariableInput":{"type":"object","properties":{"key":{"type":"string","example":"name","description":"The key of the variable, matching `^[A-Za-z0-9_]+$`; unique within the template."},"type":{"type":"string","enum":["string","number","boolean","object","list"],"description":"The type of the variable."},"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"object","additionalProperties":{}},{"type":"array","items":{}}],"description":"The fallback value of the variable. Must match `type`."}},"required":["key","type"]},"TemplateBrandOverrides":{"type":["object","null"],"properties":{"logo_url":{"type":["string","null"],"maxLength":512,"example":"https://cdn.example.com/acme-lockup.png","description":"An https URL a mail client can reach. `{{brand.logo_url}}`. `null` sends no logo even when the brand kit has one."},"primary_color":{"type":["string","null"],"example":"#1a73e8","description":"A hex colour such as `#1a73e8`. `{{brand.primary_color}}`."},"accent_color":{"type":["string","null"],"example":"#f59e0b","description":"A hex colour such as `#f59e0b`. `{{brand.accent_color}}`."},"font":{"type":["string","null"],"enum":["system","helvetica","arial","verdana","georgia","times","courier",null],"description":"A font key. `{{brand.font}}` resolves it to a stack."},"button_style":{"type":["string","null"],"enum":["square","rounded","pill",null],"description":"A button shape. `{{brand.button_radius}}` resolves it to the CSS length it means."},"company_name":{"type":["string","null"],"maxLength":120,"example":"Acme","description":"`{{brand.company_name}}`."},"address":{"type":["string","null"],"maxLength":300,"example":"1 Example Street","description":"`{{brand.address}}`."},"footer_text":{"type":["string","null"],"maxLength":300,"description":"`{{brand.footer_text}}`."}},"additionalProperties":false,"description":"A template's own values for the project's brand fields, for a one-off that should not wear the project brand. A field left out inherits the brand kit; a field set to `null` takes the platform default even when the kit has a value. On create and update the object replaces the stored set whole rather than merging into it, and `null` clears it. `null` on a retrieved template means it pins nothing."},"ListTemplatesResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/TemplateListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"TemplateListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","published"]},"published_at":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"alias":{"type":"string","example":"welcome"}},"required":["id","name","status","published_at","created_at","updated_at"],"additionalProperties":false},"Template":{"type":"object","properties":{"object":{"type":"string","enum":["template"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"current_version_id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d18"},"name":{"type":"string"},"alias":{"type":"string","example":"welcome"},"from":{"type":"string","example":"Acme <hello@acme.com>"},"subject":{"type":"string","example":"Welcome, {{name}}"},"reply_to":{"type":["array","null"],"items":{"type":"string"}},"html":{"type":"string"},"text":{"type":"string"},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariable"}},"brand_overrides":{"$ref":"#/components/schemas/TemplateBrandOverrides"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"status":{"type":"string","enum":["draft","published"]},"published_at":{"type":["string","null"]},"has_unpublished_versions":{"type":"boolean"}},"required":["object","id","current_version_id","name","reply_to","html","variables","brand_overrides","created_at","updated_at","status","published_at","has_unpublished_versions"],"additionalProperties":false},"TemplateVariable":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d19"},"key":{"type":"string","example":"name"},"type":{"type":"string","enum":["string","number","boolean","object","list"]},"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"object","additionalProperties":{}},{"type":"array","items":{}}],"description":"The fallback value of the variable. Must match `type`."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","key","type","created_at","updated_at"],"additionalProperties":false},"UpdateTemplateResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"object":{"type":"string","enum":["template"]}},"required":["id","object"],"additionalProperties":false},"UpdateTemplateOptions":{"type":"object","properties":{"name":{"type":"string","description":"The name of the template."},"alias":{"type":["string","null"],"example":"welcome","description":"The alias of the template. `null` removes it."},"from":{"type":["string","null"],"example":"Acme <hello@acme.com>","description":"Sender email address. `null` clears it."},"subject":{"type":["string","null"],"example":"Welcome, {{name}}","description":"Email subject. `null` clears it."},"reply_to":{"type":"array","items":{"type":"string"},"description":"Reply-to email addresses."},"html":{"type":"string","example":"<p>Hello {{name}}</p>","description":"The HTML version of the template. May carry `{{key}}` placeholders."},"text":{"type":"string","example":"Hello {{name}}","description":"The plain text version of the template. May carry `{{key}}` placeholders."},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariableInput"},"description":"The variables the bodies use. Every `{{key}}` must be declared here, and every declared key must be used."},"brand_overrides":{"$ref":"#/components/schemas/TemplateBrandOverrides"}}},"RemoveTemplateResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["template"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"PublishTemplateResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"object":{"type":"string","enum":["template"]}},"required":["id","object"],"additionalProperties":false},"DuplicateTemplateResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"object":{"type":"string","enum":["template"]}},"required":["id","object"],"additionalProperties":false},"TemplatePreview":{"type":"object","properties":{"object":{"type":"string","enum":["template_preview"]},"template_id":{"type":"string","format":"uuid"},"version_number":{"type":"integer"},"subject":{"type":["string","null"]},"html":{"type":"string","description":"The rendered HTML after the dashboard preview's sanitizer, with remote images withheld. Safe to place in a sandboxed iframe's `srcdoc`, and nowhere else: `style` and `class` survive."},"text":{"type":["string","null"]},"missing_variables":{"type":"array","items":{"type":"string"},"description":"Declared variables with neither a value nor a fallback. Their placeholders are left in the output; a send would refuse them."}},"required":["object","template_id","version_number","subject","html","text","missing_variables"],"additionalProperties":false},"TemplatePreviewRequest":{"type":"object","properties":{"variables":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"}]},"description":"Values by key, as a send takes them. Undeclared keys are refused."},"version":{"type":"integer","exclusiveMinimum":0,"description":"A `version_number` of this template. The current version when absent."}}},"TemplateTest":{"type":"object","properties":{"object":{"type":"string","enum":["template_test"]},"template_id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"version_number":{"type":"integer","description":"The version that was sent."},"data":{"type":"array","items":{"$ref":"#/components/schemas/TemplateTestEmail"}}},"required":["object","template_id","version_number","data"],"additionalProperties":false},"TemplateTestEmail":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The email created for this address."},"to":{"type":"string","example":"ada@example.com"}},"required":["id","to"],"additionalProperties":false},"TemplateTestOptions":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string"},"description":"One to 5 addresses. Duplicates (ignoring case) are sent once.","example":["ada@example.com"]},"from":{"type":"string","example":"Acme <hello@acme.com>","description":"The sender for the test. Required when the template has none; wins when it has one."},"variables":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"}]},"description":"Values for the declared variables, as a send takes them. A variable left out uses its fallback; one with no fallback must be given.","example":{"name":"Ada"}}},"required":["to"]},"TemplateVersionList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVersion"}}},"required":["object","has_more","data"],"additionalProperties":false},"TemplateVersion":{"type":"object","properties":{"object":{"type":"string","enum":["template_version"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d18"},"version_number":{"type":"integer"},"current":{"type":"boolean","description":"Whether this is the version `GET /templates/{id}` shows and edits write."},"published":{"type":"boolean","description":"Whether sends use this version."},"published_at":{"type":["string","null"]},"created_at":{"type":"string"},"subject":{"type":"string"},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariable"}}},"required":["object","id","version_number","current","published","published_at","created_at","variables"],"additionalProperties":false},"RestoredTemplateVersion":{"type":"object","properties":{"object":{"type":"string","enum":["template"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"version_number":{"type":"integer","description":"The new draft version's number."}},"required":["object","id","version_number"],"additionalProperties":false},"ListStartersResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/StarterListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"StarterListItem":{"type":"object","properties":{"object":{"type":"string","enum":["starter"]},"slug":{"type":"string","enum":["welcome-minimal","welcome","password-reset-card","magic-link","password-reset","sunny-promo","storefront","gift-card","editorial-launch","glow-offer","newsletter","order-confirmation","shipping","receipt","invoice"],"example":"receipt"},"name":{"type":"string","example":"Receipt"},"summary":{"type":"string"},"category":{"type":"string","example":"Billing"},"subject":{"type":"string","example":"Your receipt from {{brand.company_name}}"},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariableInput"},"description":"The send variables the starter's bodies use. A copy declares exactly these; fill them at send time."}},"required":["object","slug","name","summary","category","subject","variables"],"additionalProperties":false},"Starter":{"type":"object","properties":{"object":{"type":"string","enum":["starter"]},"slug":{"type":"string","enum":["welcome-minimal","welcome","password-reset-card","magic-link","password-reset","sunny-promo","storefront","gift-card","editorial-launch","glow-offer","newsletter","order-confirmation","shipping","receipt","invoice"],"example":"receipt"},"name":{"type":"string","example":"Receipt"},"summary":{"type":"string"},"category":{"type":"string","example":"Billing"},"subject":{"type":"string","example":"Your receipt from {{brand.company_name}}"},"variables":{"type":"array","items":{"$ref":"#/components/schemas/TemplateVariableInput"},"description":"The send variables the starter's bodies use. A copy declares exactly these; fill them at send time."},"html":{"type":"string"},"text":{"type":"string"},"sample_variables":{"type":"object","additionalProperties":{"type":"string"},"description":"Illustrative values for the declared variables. Never sent, never stored."}},"required":["object","slug","name","summary","category","subject","variables","html","text","sample_variables"],"additionalProperties":false},"GetEmailsMetricsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["metrics"]},"start_date":{"type":"string"},"end_date":{"type":"string"},"metrics":{"type":"array","items":{"type":"string"}},"dimensions":{"type":"array","items":{"type":"string"}},"granularity":{"type":"string","enum":["hourly","daily","weekly","monthly"]},"totals":{"type":"object","additionalProperties":{"type":"number"}},"data_as_of":{"type":"string"},"data":{"type":"array","items":{"type":"object","additionalProperties":{"anyOf":[{"type":"number"},{"type":"string"}]}}}},"required":["object","start_date","end_date","metrics","dimensions","granularity","totals","data_as_of"],"additionalProperties":false},"ListReceivedEmailsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedEmailListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ReceivedEmailListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"to":{"type":"array","items":{"type":"string"}},"from":{"type":"string"},"subject":{"type":["string","null"]},"message_id":{"type":"string"},"bcc":{"type":["array","null"],"items":{"type":"string"}},"cc":{"type":["array","null"],"items":{"type":"string"}},"reply_to":{"type":["array","null"],"items":{"type":"string"}},"dropped_reason":{"type":["string","null"],"enum":["storage_quota","daily_cap","virus","parse_failed","no_mailbox","team_blocked",null],"description":"Why the message was recorded without its content. `null` for a message we stored. A dropped message has `html: null`, `text: null` and no attachments."},"created_at":{"type":"string","example":"2026-09-09T10:16:44.902Z"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedEmailAttachment"}}},"required":["id","to","from","subject","message_id","bcc","cc","reply_to","dropped_reason","created_at","attachments"],"additionalProperties":false},"ReceivedEmailAttachment":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"660e8400-e29b-41d4-a716-446655440000"},"filename":{"type":["string","null"]},"content_type":{"type":"string","example":"application/pdf"},"content_id":{"type":"string"},"content_disposition":{"type":"string","enum":["inline","attachment"]},"size":{"type":"integer","example":2048}},"required":["id","filename","content_type","content_disposition","size"],"additionalProperties":false},"GetReceivedEmailResponse":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"to":{"type":"array","items":{"type":"string"}},"from":{"type":"string","example":"Ronald Williams <ronald.williams@example.com>"},"subject":{"type":"string"},"message_id":{"type":"string","example":"<CAF1042.damaged@mail.example.com>"},"bcc":{"type":["array","null"],"items":{"type":"string"}},"cc":{"type":["array","null"],"items":{"type":"string"}},"reply_to":{"type":["array","null"],"items":{"type":"string"}},"received_for":{"type":"array","items":{"type":"string"},"description":"The addresses of yours this message was accepted for. Route on this rather than on `to`, which is whatever the sender wrote."},"html":{"type":["string","null"]},"text":{"type":["string","null"]},"headers":{"type":["object","null"],"additionalProperties":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"dropped_reason":{"type":["string","null"],"enum":["storage_quota","daily_cap","virus","parse_failed","no_mailbox","team_blocked",null],"description":"Why the message was recorded without its content. `null` for a message we stored. A dropped message has `html: null`, `text: null` and no attachments."},"created_at":{"type":"string","example":"2026-09-09T10:16:44.902Z"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedEmailAttachment"}}},"required":["object","id","to","from","subject","message_id","bcc","cc","reply_to","received_for","html","text","headers","dropped_reason","created_at","attachments"],"additionalProperties":false},"ListAttachmentsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedAttachmentListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ReceivedAttachmentListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"660e8400-e29b-41d4-a716-446655440000"},"filename":{"type":["string","null"]},"content_type":{"type":"string","example":"application/pdf"},"content_id":{"type":"string"},"content_disposition":{"type":"string","enum":["inline","attachment"]},"size":{"type":"integer","example":2048},"download_url":{"type":"string","description":"A signed URL for the bytes, valid for 15 minutes. Absent — together with `expires_at` — when the part was not stored."},"expires_at":{"type":"string","example":"2026-09-09T10:31:44.902Z"}},"required":["id","filename","content_type","content_disposition","size"],"additionalProperties":false},"ReceivedAttachment":{"type":"object","properties":{"object":{"type":"string","enum":["attachment"]},"id":{"type":"string","format":"uuid","example":"660e8400-e29b-41d4-a716-446655440000"},"filename":{"type":["string","null"]},"content_type":{"type":"string","example":"application/pdf"},"content_id":{"type":"string"},"content_disposition":{"type":"string","enum":["inline","attachment"]},"size":{"type":"integer","example":2048},"download_url":{"type":"string","description":"A signed URL for the bytes, valid for 15 minutes. Absent — together with `expires_at` — when the part was not stored."},"expires_at":{"type":"string","example":"2026-09-09T10:31:44.902Z"}},"required":["object","id","filename","content_type","content_disposition","size"],"additionalProperties":false},"DeleteReceivedEmailResponse":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"ShareEmailResponse":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"url":{"type":"string","example":"https://share.example.com/9xKq2..."},"expires_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"}},"required":["object","id","url","expires_at"],"additionalProperties":false},"ShareEmailOptions":{"type":"object","properties":{"expires_in":{"type":"string","example":"24h","description":"A duration such as `10m`, `2 hours` or `1 day`."}}},"DeleteEmailShareResponse":{"type":"object","properties":{"object":{"type":"string","enum":["email_share"]},"id":{"type":"string","format":"uuid"},"revoked_at":{"type":"string","example":"2026-09-10T09:00:00.000Z"}},"required":["object","id","revoked_at"],"additionalProperties":false},"EmailShareList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailShare"}}},"required":["object","has_more","data"],"additionalProperties":false},"EmailShare":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0198f4c1-0000-7000-8000-000000000000"},"email_id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"status":{"type":"string","enum":["active","expired","revoked"],"description":"`active` while the link still opens the page, `expired` once `expires_at` has passed, `revoked` once it was withdrawn. A withdrawn link that has also expired reads `revoked`."},"created_at":{"type":"string","example":"2026-09-09T12:00:00.000Z"},"expires_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"revoked_at":{"type":["string","null"]},"created_by_user_id":{"type":["string","null"],"format":"uuid"},"created_by_api_key_id":{"type":["string","null"],"format":"uuid"}},"required":["id","email_id","status","created_at","expires_at","revoked_at","created_by_user_id","created_by_api_key_id"],"additionalProperties":false},"RetrievedAttachment":{"type":"object","properties":{"object":{"type":"string","enum":["attachment"]},"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"content_type":{"type":"string"},"content_id":{"type":"string"},"content_disposition":{"type":"string","enum":["inline","attachment"]},"download_url":{"type":"string"},"expires_at":{"type":"string"},"size":{"type":"integer"}},"required":["object","id","filename","content_type","content_disposition","download_url","expires_at","size"],"additionalProperties":false},"AttachmentList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AttachmentListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"AttachmentListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"content_type":{"type":"string"},"content_id":{"type":"string"},"content_disposition":{"type":"string","enum":["inline","attachment"]},"download_url":{"type":"string"},"expires_at":{"type":"string"},"size":{"type":"integer"}},"required":["id","filename","content_type","content_disposition","download_url","expires_at","size"],"additionalProperties":false},"CreateBatchEmailsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false},"SendBatchEmailsRequest":{"type":"array","items":{"$ref":"#/components/schemas/SendEmailRequest"},"minItems":1,"maxItems":100},"SendEmailRequest":{"type":"object","properties":{"from":{"type":"string","example":"Acme <orders@send.example.com>","description":"Required, unless `template` names a published version that sets a sender. The request's value wins."},"to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"maxItems":50,"example":["ronald.williams@example.com"]},"subject":{"type":"string","example":"Hello World","description":"Required, unless `template` names a published version that sets a subject. The request's value wins."},"bcc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"cc":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"reply_to":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"html":{"type":"string"},"text":{"type":"string"},"template":{"$ref":"#/components/schemas/EmailTemplateInput"},"headers":{"type":"object","additionalProperties":{"type":"string"}},"scheduled_at":{"type":"string","example":"2026-09-10T12:00:00.000Z","description":"An ISO 8601 instant, or a phrase such as `in 2 hours`, `tomorrow at 9am` or `next tuesday 9am` — phrases are read as UTC. Between one minute and thirty days from now."},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Attachment"}},"tags":{"type":"array","items":{"$ref":"#/components/schemas/Tag"}},"topic_id":{"type":"string"}},"required":["to"]},"EmailTemplateInput":{"type":"object","properties":{"id":{"type":"string"},"variables":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"}]}}},"required":["id"]},"Attachment":{"type":"object","properties":{"content":{"type":"string"},"filename":{"type":"string"},"path":{"type":"string"},"content_type":{"type":"string"},"content_id":{"type":"string"}}},"Tag":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]},"SendEmailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"}},"required":["id"],"additionalProperties":false},"EmailList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Email"}}},"required":["object","has_more","data"],"additionalProperties":false},"Email":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"id":{"type":"string","format":"uuid","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"message_id":{"type":["string","null"]},"to":{"type":"array","items":{"type":"string"}},"from":{"type":"string"},"created_at":{"type":"string","example":"2026-09-09T12:00:00.000Z"},"subject":{"type":"string"},"html":{"type":["string","null"]},"text":{"type":["string","null"]},"bcc":{"type":"array","items":{"type":"string"}},"cc":{"type":"array","items":{"type":"string"}},"reply_to":{"type":"array","items":{"type":"string"}},"last_event":{"type":"string","enum":["queued","scheduled","sent","delivered","delivery_delayed","bounced","complained","opened","clicked","failed","suppressed","canceled"]},"scheduled_at":{"type":["string","null"],"example":"2026-09-10T12:00:00.000Z","description":"When the email is, or was, due to go. This is the last requested send time: an email that has already gone, and a scheduled one that was canceled, both keep it. `last_event` says which."},"tags":{"type":"object","additionalProperties":{"type":"string"},"example":{"invoice":"1042"}}},"required":["object","id","message_id","to","from","created_at","subject","html","text","bcc","cc","reply_to","last_event","scheduled_at"],"additionalProperties":false},"EmailRef":{"type":"object","properties":{"object":{"type":"string","enum":["email"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"UpdateEmailOptions":{"type":"object","properties":{"scheduled_at":{"type":"string","example":"2026-09-10T12:00:00.000Z","description":"An ISO 8601 instant, or a phrase such as `in 2 hours`, `tomorrow at 9am` or `next tuesday 9am` — phrases are read as UTC. Between one minute and thirty days from now."}},"required":["scheduled_at"]},"CreateContactPropertyResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_property"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"CreateContactPropertyOptions":{"type":"object","properties":{"key":{"type":"string","example":"company_name","description":"The property key. Max length is 50 characters. Only alphanumeric characters and underscores are allowed."},"type":{"type":"string","enum":["string","number"]},"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}],"description":"The default value to use when the property is not set for a contact. Must match `type`."}},"required":["key","type"]},"ListContactPropertiesResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListContactPropertiesItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListContactPropertiesItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"key":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"created_at":{"type":"string"}},"required":["id","key","type","created_at"],"additionalProperties":false},"GetContactPropertyResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_property"]},"id":{"type":"string","format":"uuid"},"key":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean"]},"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"created_at":{"type":"string"}},"required":["object","id","key","type","created_at"],"additionalProperties":false},"UpdateContactPropertyResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_property"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"UpdateContactPropertyOptions":{"type":"object","properties":{"fallback_value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]}}},"RemoveContactPropertyResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_property"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"CreateContactImportResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_import"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"ListContactImportsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactImport"}}},"required":["object","has_more","data"],"additionalProperties":false},"ContactImport":{"type":"object","properties":{"object":{"type":"string","enum":["contact_import"]},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","in_progress","completed","failed"]},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]},"counts":{"$ref":"#/components/schemas/ContactImportCounts"}},"required":["object","id","status","created_at","completed_at","counts"],"additionalProperties":false},"ContactImportCounts":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of rows processed by the import."},"created":{"type":"integer","description":"Number of contacts created by the import."},"updated":{"type":"integer","description":"Number of contacts updated by the import."},"skipped":{"type":"integer","description":"Number of rows skipped by the import."},"failed":{"type":"integer","description":"Number of rows that failed during the import."}},"required":["total","created","updated","skipped","failed"],"additionalProperties":false},"CreateContactResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"CreateContactOptions":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320,"example":"ronald.williams@example.com"},"first_name":{"type":"string","example":"Steve"},"last_name":{"type":"string","example":"Wozniak"},"unsubscribed":{"type":"boolean"},"properties":{"type":"object","additionalProperties":{},"description":"A map of custom property keys and values. Every key must be a declared contact property; `null` removes a key."},"segments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}},"topics":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"subscription":{"type":"string","enum":["opt_in","opt_out"]}},"required":["id","subscription"]}}},"required":["email"]},"ListContactsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListContactsItem"}}},"required":["object","data"],"additionalProperties":false},"ListContactsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"created_at":{"type":"string"},"unsubscribed":{"type":"boolean"}},"required":["id","email","first_name","last_name","created_at","unsubscribed"],"additionalProperties":false},"GetContactResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"created_at":{"type":"string"},"unsubscribed":{"type":"boolean"},"properties":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"A map of custom property keys and values."}},"required":["object","id","email","first_name","last_name","created_at","unsubscribed","properties"],"additionalProperties":false},"UpdateContactResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid"}},"required":["object","id"],"additionalProperties":false},"UpdateContactOptions":{"type":"object","properties":{"email":{"type":"string","minLength":3,"maxLength":320,"example":"ronald.williams@example.com"},"first_name":{"type":"string"},"last_name":{"type":"string"},"unsubscribed":{"type":"boolean"},"properties":{"type":"object","additionalProperties":{},"description":"A map of custom property keys and values. Every key must be a declared contact property; `null` removes a key."}}},"RemoveContactResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"CreateSegmentResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["segment"]}},"required":["id","object"],"additionalProperties":false},"CreateSegmentOptions":{"type":"object","properties":{"name":{"type":"string","example":"Active Users","description":"The name of the segment."},"filter":{"type":["object","null"],"additionalProperties":{},"description":"Filter conditions for the segment: `{ all | any | not: [ … ] }` over `{ field, op, value }` and `{ topic, subscription }`. Fields: `email`, `first_name`, `last_name`, `unsubscribed`, `created_at`, `properties.<key>`. Ops: `eq`, `neq`, `contains`, `exists`, `gt`, `gte`, `lt`, `lte`, `in`. Nesting to depth 3, at most 20 conditions. `null` means explicit membership only.","example":{"all":[{"field":"properties.plan","op":"eq","value":"pro"},{"field":"unsubscribed","op":"eq","value":false},{"any":[{"field":"first_name","op":"exists"},{"field":"properties.score","op":"gt","value":10}]}]}}},"required":["name"]},"ListSegmentsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListSegmentsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListSegmentsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string"}},"required":["id","name","created_at"],"additionalProperties":false},"SegmentPreview":{"type":"object","properties":{"object":{"type":"string","enum":["segment_preview"]},"contacts":{"type":"integer","description":"How many contacts the filter matches right now."}},"required":["object","contacts"],"additionalProperties":false},"SegmentPreviewRequest":{"type":"object","properties":{"filter":{"type":"object","additionalProperties":{},"description":"A segment filter, exactly as `POST /segments` takes it."}},"required":["filter"]},"SegmentContactList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListContactsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"SegmentMetrics":{"type":"object","properties":{"object":{"type":"string","enum":["segment_metrics"]},"segment_id":{"type":"string","format":"uuid"},"contacts":{"type":"integer"},"subscribed":{"type":"integer"},"unsubscribed":{"type":"integer"}},"required":["object","segment_id","contacts","subscribed","unsubscribed"],"additionalProperties":false},"GetSegmentResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["segment"]},"name":{"type":"string"},"filter":{"type":["object","null"],"additionalProperties":{},"description":"Filter conditions for the segment: `{ all | any | not: [ … ] }` over `{ field, op, value }` and `{ topic, subscription }`. Fields: `email`, `first_name`, `last_name`, `unsubscribed`, `created_at`, `properties.<key>`. Ops: `eq`, `neq`, `contains`, `exists`, `gt`, `gte`, `lt`, `lte`, `in`. Nesting to depth 3, at most 20 conditions. `null` means explicit membership only.","example":{"all":[{"field":"properties.plan","op":"eq","value":"pro"},{"field":"unsubscribed","op":"eq","value":false},{"any":[{"field":"first_name","op":"exists"},{"field":"properties.score","op":"gt","value":10}]}]}},"created_at":{"type":"string"}},"required":["id","object","name","filter","created_at"],"additionalProperties":false},"UpdateSegmentResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["segment"]}},"required":["id","object"],"additionalProperties":false},"UpdateSegmentOptions":{"type":"object","properties":{"name":{"type":"string","example":"Active Users","description":"The name of the segment."}},"required":["name"]},"RemoveSegmentResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["segment"]},"deleted":{"type":"boolean","enum":[true]}},"required":["id","object","deleted"],"additionalProperties":false},"ListContactSegmentsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListContactSegmentsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListContactSegmentsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","description":"When the contact was added to the segment; for a contact matched by the segment's filter, the later of the segment's and the contact's creation."}},"required":["id","name","created_at"],"additionalProperties":false},"AddContactToSegmentResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_segment"]},"contact_id":{"type":"string","format":"uuid"},"segment_id":{"type":"string","format":"uuid"}},"required":["object","contact_id","segment_id"],"additionalProperties":false},"RemoveContactFromSegmentResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_segment"]},"contact_id":{"type":"string","format":"uuid"},"segment_id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","contact_id","segment_id","deleted"],"additionalProperties":false},"BillingPaygResponse":{"type":"object","properties":{"object":{"type":"string","enum":["billing_payg"]},"enabled":{"type":"boolean"},"overage_ceiling_emails":{"type":["integer","null"]}},"required":["object","enabled","overage_ceiling_emails"],"additionalProperties":false},"BillingPaygRequest":{"type":"object","properties":{"enabled":{"type":"boolean","description":"The \"Continue using the service beyond your quota.\" toggle."}},"required":["enabled"]},"BillingSpendCapResponse":{"type":"object","properties":{"object":{"type":"string","enum":["billing_spend_cap"]},"emails":{"type":"integer"},"is_default":{"type":"boolean"},"alert_pcts":{"type":"array","items":{"type":"integer"}},"used_emails":{"type":"integer"},"sending_paused_at":{"type":["string","null"]},"sending_paused_reason":{"type":["string","null"]}},"required":["object","emails","is_default","alert_pcts","used_emails","sending_paused_at","sending_paused_reason"],"additionalProperties":false},"BillingSpendCapRequest":{"type":"object","properties":{"emails":{"type":"integer","description":"The most this project may send in a month, in billable recipients."},"alert_pcts":{"type":"array","items":{"type":"integer"},"description":"Whole percentages of the cap to be warned at. Omit to leave the current ladder alone."}},"required":["emails"]},"TeamAddon":{"type":"object","properties":{"object":{"type":"string","enum":["team_addon"]},"addon_code":{"type":"string"},"name":{"type":"string"},"monthly_price_cents":{"type":"integer"},"quantity":{"type":"integer"},"status":{"type":"string"},"requested_at":{"type":"string"},"provisioned_at":{"type":["string","null"]}},"required":["object","addon_code","name","monthly_price_cents","quantity","status","requested_at","provisioned_at"],"additionalProperties":false},"PurchaseAddonRequest":{"type":"object","properties":{"addon_code":{"type":"string","enum":["extra_domains_100","dedicated_ip","sso","marketing_5k","marketing_10k","marketing_15k","marketing_25k","marketing_50k","marketing_100k","marketing_150k","inbox_storage_100gb","inbox_seat"],"description":"`extra_domains_100`, `dedicated_ip`, `sso`, `inbox_storage_100gb`, `inbox_seat`, or one of the marketing plans: `marketing_5k`, `marketing_10k`, `marketing_15k`, `marketing_25k`, `marketing_50k`, `marketing_100k`, `marketing_150k`."},"quantity":{"type":"integer","minimum":1,"maximum":100,"description":"Units held after the call (a set, not an increment). Default 1. For `inbox_seat` it must equal the team's open mailboxes minus the number the plan includes — seats follow the mailboxes, and any other number is refused."},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"],"description":"`dedicated_ip` only: the region the pool should live in. Defaults to `us-east-1`."},"expected_daily_volume":{"type":"integer","minimum":1,"maximum":100000000,"deprecated":true,"description":"Deprecated and ignored. There is no volume requirement for a dedicated IP: `GET /billing` reports what we recommend and what your team actually sends, and the choice is yours. Still accepted so existing clients keep working."}},"required":["addon_code"]},"GetContactTopicsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/GetContactTopicsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"GetContactTopicsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"subscription":{"type":"string","enum":["opt_in","opt_out"]}},"required":["id","name","description","subscription"],"additionalProperties":false},"UpdateContactTopicsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["contact_topics"]},"contact_id":{"type":"string","format":"uuid"},"topics":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"subscription":{"type":"string","enum":["opt_in","opt_out"]}},"required":["id","subscription"],"additionalProperties":false}}},"required":["object","contact_id","topics"],"additionalProperties":false},"UpdateContactTopicsOptions":{"type":"object","properties":{"topics":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"subscription":{"type":"string","enum":["opt_in","opt_out"]}},"required":["id","subscription"]}}},"required":["topics"]},"CreateTopicResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["topic"]}},"required":["id","object"],"additionalProperties":false},"CreateTopicOptions":{"type":"object","properties":{"name":{"type":"string","example":"Newsletter","description":"The name of the topic. Max 50 characters."},"default_subscription":{"type":"string","enum":["opt_in","opt_out"],"description":"The default subscription status for the topic. Cannot be changed after creation."},"description":{"type":"string","description":"A description of the topic. Max 200 characters."},"visibility":{"type":"string","enum":["public","private"],"description":"The visibility of the topic; `private` when omitted. Public topics are visible to all contacts on the unsubscribe page. Private topics are only visible to opted-in contacts."}},"required":["name","default_subscription"]},"ListTopicsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListTopicsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListTopicsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"default_subscription":{"type":"string","enum":["opt_in","opt_out"]},"visibility":{"type":"string","enum":["public","private"]},"created_at":{"type":"string"}},"required":["id","name","description","default_subscription","visibility","created_at"],"additionalProperties":false},"GetTopicResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["topic"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string"},"default_subscription":{"type":"string","enum":["opt_in","opt_out"]},"visibility":{"type":"string","enum":["public","private"]},"created_at":{"type":"string"}},"required":["object","id","name","description","default_subscription","visibility","created_at"],"additionalProperties":false},"UpdateTopicResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["topic"]}},"required":["id","object"],"additionalProperties":false},"UpdateTopicOptions":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"visibility":{"type":"string","enum":["public","private"]}}},"RemoveTopicResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["topic"]},"deleted":{"type":"boolean","enum":[true]}},"required":["id","object","deleted"],"additionalProperties":false},"CreateBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["broadcast"]}},"required":["id","object"],"additionalProperties":false},"CreateBroadcastOptions":{"type":"object","properties":{"name":{"type":"string","description":"Name of the broadcast.","example":"November announcements"},"segment_id":{"type":"string","description":"Unique identifier of the segment this broadcast will be sent to.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"audience_id":{"type":"string","deprecated":true,"description":"Use `segment_id` instead. Unique identifier of the segment this broadcast will be sent to."},"from":{"type":"string","description":"The email address of the sender.","example":"Acme <news@send.example.com>"},"subject":{"type":"string","description":"The subject line of the email.","example":"Hello World"},"reply_to":{"type":"array","items":{"type":"string"},"description":"The email addresses to which replies should be sent."},"preview_text":{"type":"string","description":"The preview text of the email.","example":"Here are our announcements"},"html":{"type":"string","description":"The HTML version of the message.","example":"<p>Hello {{{FIRST_NAME|there}}}!</p>"},"text":{"type":"string","description":"The plain text version of the message.","example":"Hello {{{FIRST_NAME|there}}}!"},"topic_id":{"type":"string","description":"The topic ID that the broadcast will be scoped to.","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"},"template":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"description":"Create the broadcast from a published template: its `html` and `text` (and `reply_to`, when this request sends none) are copied into the broadcast once. Mutually exclusive with `html` and `text`. Later template edits do not change the broadcast."},"send":{"type":"boolean","description":"Whether to send the broadcast immediately or keep it as a draft.\n"},"scheduled_at":{"type":"string","description":"Schedule time to send the broadcast. Can only be used if `send` is true.\n","example":"2026-09-11T12:00:00.000Z"}},"required":["from","subject"]},"ListBroadcastsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListBroadcastsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListBroadcastsItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"name":{"type":"string","example":"November announcements"},"audience_id":{"type":"string","format":"uuid","deprecated":true,"description":"Deprecated. Use segment_id instead."},"segment_id":{"type":"string","format":"uuid","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"status":{"type":"string","enum":["draft","scheduled","queued","sending","sent","canceled","failed"],"example":"draft"},"created_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"scheduled_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"sent_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"topic_id":{"type":"string","format":"uuid","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"}},"required":["id","audience_id","segment_id","status","created_at"],"additionalProperties":false},"SendBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"],"additionalProperties":false},"SendBroadcastOptions":{"type":"object","properties":{"scheduled_at":{"type":"string","description":"Schedule email to be sent later. The date should be in ISO 8601 format.","example":"2026-09-11T12:00:00.000Z"}}},"CancelBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["broadcast"]}},"required":["id","object"],"additionalProperties":false},"ListBroadcastRecipientsResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListBroadcastRecipientsItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListBroadcastRecipientsItem":{"type":"object","properties":{"id":{"type":"string","description":"Opaque cursor identifying this row, used for pagination.","example":"MjAyNi0wOS0xMVQxMjowMDowMC4wMDBafGUxNjlhYTQ1LTFlY2YtNDE4My05OTU1LWIxNDk5ZDU3MDFkMw"},"contact_id":{"type":["string","null"],"format":"uuid","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"email":{"type":"string","example":"ronald.williams@example.com"},"count":{"type":"integer","description":"The number of times this recipient triggered the event. Only present when `type` is `opened` or `clicked`.","example":3},"bounce_type":{"type":"string","enum":["permanent","transient","undetermined"],"description":"The type of bounce. Only present when `type` is `bounced`."},"clicked_links":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","example":"https://example.com/pricing"},"clicks":{"type":"integer","example":2}},"required":["url","clicks"],"additionalProperties":false},"description":"The links this recipient clicked. Only present when `type` is `clicked`."}},"required":["id","contact_id","email"],"additionalProperties":false},"ListBroadcastClickedLinksResponseSuccess":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ListBroadcastClickedLinksItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"ListBroadcastClickedLinksItem":{"type":"object","properties":{"id":{"type":"string","description":"An opaque cursor for this row, used only for pagination. It does not identify any entity."},"url":{"type":"string","example":"https://example.com/pricing"},"clicks":{"type":"integer","example":42},"unique_clicks":{"type":"integer","example":30}},"required":["id","url","clicks","unique_clicks"],"additionalProperties":false},"BroadcastCompliance":{"type":"object","properties":{"object":{"type":"string","enum":["broadcast_compliance"]},"broadcast_id":{"type":"string","format":"uuid","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"sendable":{"type":"boolean","description":"Every condition passed: a send would be accepted now."},"conditions":{"type":"array","items":{"$ref":"#/components/schemas/BroadcastComplianceCondition"}}},"required":["object","broadcast_id","sendable","conditions"],"additionalProperties":false},"BroadcastComplianceCondition":{"type":"object","properties":{"condition":{"type":"string","enum":["sending_domain","postal_address","segment","marketing_enabled","team_can_send","body"]},"passed":{"type":"boolean"},"name":{"type":"string","enum":["invalid_idempotency_key","validation_error","missing_api_key","invalid_api_key","restricted_api_key","email_above_quota","invalid_permission","suspended_api_key","not_found","method_not_allowed","concurrent_idempotent_requests","invalid_idempotent_request","resource_locked","receiving_mx_in_use","invalid_attachment","invalid_parameter","missing_required_field","missing_required_parameter","daily_quota_exceeded","monthly_quota_exceeded","marketing_quota_exceeded","rate_limit_exceeded","application_error","not_implemented","service_unavailable"],"description":"The error a send would answer with, when it failed."},"message":{"type":"string","description":"The sentence a send would answer with, when it failed."}},"required":["condition","passed"],"additionalProperties":false},"DuplicateBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["broadcast"]}},"required":["id","object"],"additionalProperties":false},"BroadcastTest":{"type":"object","properties":{"object":{"type":"string","enum":["broadcast_test"]},"broadcast_id":{"type":"string","format":"uuid","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"data":{"type":"array","items":{"$ref":"#/components/schemas/BroadcastTestEmail"}}},"required":["object","broadcast_id","data"],"additionalProperties":false},"BroadcastTestEmail":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The email created for this address."},"to":{"type":"string","example":"ada@example.com"}},"required":["id","to"],"additionalProperties":false},"BroadcastTestOptions":{"type":"object","properties":{"to":{"type":"array","items":{"type":"string"},"description":"One to 5 addresses. Duplicates (ignoring case) are sent once.","example":["ada@example.com"]}},"required":["to"]},"GetBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"name":{"type":"string","example":"November announcements"},"audience_id":{"type":["string","null"],"format":"uuid","deprecated":true,"description":"Deprecated: use `segment_id` instead."},"segment_id":{"type":["string","null"],"format":"uuid","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"from":{"type":"string","example":"Acme <news@send.example.com>"},"subject":{"type":"string","example":"Hello World"},"reply_to":{"type":"array","items":{"type":"string"}},"preview_text":{"type":"string","example":"Here are our announcements"},"status":{"type":"string","enum":["draft","scheduled","queued","sending","sent","canceled","failed"],"example":"draft"},"created_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"scheduled_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"sent_at":{"type":"string","example":"2026-09-11T12:00:00.000Z"},"text":{"type":["string","null"],"example":"Hello {{{FIRST_NAME|there}}}!"},"html":{"type":["string","null"],"example":"<p>Hello {{{FIRST_NAME|there}}}!</p>"},"topic_id":{"type":["string","null"],"format":"uuid","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"}},"required":["id","audience_id","segment_id","from","subject","reply_to","status","created_at","text","html","topic_id"],"additionalProperties":false},"UpdateBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["broadcast"]}},"required":["id","object"],"additionalProperties":false},"UpdateBroadcastOptions":{"type":"object","properties":{"name":{"type":"string","description":"Name of the broadcast.","example":"November announcements"},"segment_id":{"type":"string","description":"Unique identifier of the segment this broadcast will be sent to.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"audience_id":{"type":"string","deprecated":true,"description":"Use `segment_id` instead. Unique identifier of the segment this broadcast will be sent to."},"from":{"type":"string","description":"The email address of the sender.","example":"Acme <news@send.example.com>"},"subject":{"type":"string","description":"The subject line of the email.","example":"Hello World"},"reply_to":{"type":"array","items":{"type":"string"},"description":"The email addresses to which replies should be sent."},"preview_text":{"type":"string","description":"The preview text of the email.","example":"Here are our announcements"},"html":{"type":"string","description":"The HTML version of the message.","example":"<p>Hello {{{FIRST_NAME|there}}}!</p>"},"text":{"type":"string","description":"The plain text version of the message.","example":"Hello {{{FIRST_NAME|there}}}!"},"topic_id":{"type":"string","description":"The topic ID that the broadcast will be scoped to.","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"}}},"RemoveBroadcastResponseSuccess":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["broadcast"]},"deleted":{"type":"boolean","enum":[true]}},"required":["id","object","deleted"],"additionalProperties":false},"OAuthTokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer"},"refresh_token":{"type":"string"},"scope":{"type":"string"}},"required":["access_token","token_type","expires_in","refresh_token","scope"],"additionalProperties":false},"OAuthError":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type","invalid_scope"]},"error_description":{"type":"string"}},"required":["error"],"additionalProperties":false},"CreateAutomationResponse":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"}},"required":["object","id"],"additionalProperties":false},"CreateAutomationRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"example":"Trial nudge","description":"The name of the automation."},"status":{"type":"string","enum":["enabled","disabled"],"description":"The initial status of the automation. Defaults to `disabled`."},"steps":{"type":"array","items":{"$ref":"#/components/schemas/AutomationStep"},"minItems":1,"maxItems":150,"description":"The steps that compose the automation workflow, at most 150. Exactly one must be a `trigger`."},"connections":{"type":"array","items":{"$ref":"#/components/schemas/AutomationConnection"},"description":"The connections between steps in the automation graph."}},"required":["name","steps","connections"]},"AutomationStep":{"type":"object","properties":{"key":{"type":"string","example":"start","description":"A unique key for this step within the automation graph."},"type":{"type":"string","enum":["trigger","send_email","delay","wait_for_event","contact_delete","condition","contact_update","add_to_segment","topic_update"],"description":"The type of automation step."},"config":{"type":"object","additionalProperties":{},"description":"Configuration for the step. The shape depends on `type`: `trigger` takes `{ event_name }`, `send_email` a `{ template: { id, variables? }, subject?, from?, reply_to? }`, `delay` a `{ duration }` or `{ until }`, `condition` a rule tree, `contact_update` literal field values, `add_to_segment` a `{ segment_id }` and `topic_update` a `{ topic_id, subscription }`."}},"required":["key","type","config"]},"AutomationConnection":{"type":"object","properties":{"from":{"type":"string","example":"start","description":"The `key` of the source step."},"to":{"type":"string","example":"welcome","description":"The `key` of the target step."},"type":{"type":"string","enum":["default","condition_met","condition_not_met","timeout","event_received"],"default":"default","description":"The type of connection. Defaults to `default`."}},"required":["from","to"],"additionalProperties":false},"ListAutomationsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AutomationListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"AutomationListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"name":{"type":"string","example":"Trial nudge"},"status":{"type":"string","enum":["enabled","disabled"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","status","created_at","updated_at"],"additionalProperties":false},"Automation":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"name":{"type":"string","example":"Trial nudge"},"status":{"type":"string","enum":["enabled","disabled"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/AutomationStepResponse"}},"connections":{"type":"array","items":{"$ref":"#/components/schemas/AutomationConnection"}}},"required":["object","id","name","status","created_at","updated_at","steps","connections"],"additionalProperties":false},"AutomationStepResponse":{"type":"object","properties":{"key":{"type":"string","example":"start"},"type":{"type":"string","enum":["trigger","send_email","delay","condition","contact_update","add_to_segment","topic_update"],"description":"The type of automation step."},"config":{"type":"object","additionalProperties":{},"description":"The step's configuration, as it was published."}},"required":["key","type","config"],"additionalProperties":false},"PatchAutomationResponse":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"}},"required":["object","id"],"additionalProperties":false},"PatchAutomationRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"The name of the automation."},"status":{"type":"string","enum":["enabled","disabled"],"description":"The status of the automation. `disabled` stops new enrolments and leaves runs already in flight alone."},"steps":{"type":"array","items":{"$ref":"#/components/schemas/AutomationStep"},"minItems":1,"maxItems":150,"description":"The steps that compose the automation workflow, at most 150. Exactly one must be a `trigger`."},"connections":{"type":"array","items":{"$ref":"#/components/schemas/AutomationConnection"},"description":"The connections between steps in the automation graph."}}},"DeleteAutomationResponse":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"DuplicateAutomationResponse":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"}},"required":["object","id"],"additionalProperties":false},"StopAutomationResponse":{"type":"object","properties":{"object":{"type":"string","enum":["automation"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"status":{"type":"string","enum":["disabled"],"description":"The status after stopping."}},"required":["object","id","status"],"additionalProperties":false},"AutomationVersionList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AutomationVersion"}}},"required":["object","has_more","data"],"additionalProperties":false},"AutomationVersion":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"version_number":{"type":"integer"},"active":{"type":"boolean","description":"Whether new enrolments run this version."},"trigger_event_name":{"type":"string"},"trigger_segment_id":{"type":["string","null"],"format":"uuid"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/AutomationStepResponse"}},"connections":{"type":"array","items":{"$ref":"#/components/schemas/AutomationConnection"}},"created_by":{"type":["object","null"],"properties":{"type":{"type":"string","enum":["user","api_key"]},"id":{"type":"string","format":"uuid"}},"required":["type","id"],"additionalProperties":false,"description":"Whoever wrote the version, or null once neither exists."},"created_at":{"type":"string"}},"required":["id","version_number","active","trigger_event_name","trigger_segment_id","steps","connections","created_by","created_at"],"additionalProperties":false},"ListAutomationRunsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AutomationRunListItem"}}},"required":["object","has_more","data"],"additionalProperties":false},"AutomationRunListItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e02"},"status":{"type":"string","enum":["running","completed","failed","cancelled"]},"failure_reason":{"type":["string","null"],"description":"Why the run ended, as a stable code, for a run that failed or was cancelled: the same value the `automation.run.failed` webhook carries. Null while it is still running and on one that completed.","example":"validation_error"},"failure_message":{"type":["string","null"],"description":"The same ending in a sentence, for a person to read. Null whenever `failure_reason` is.","example":"The domain is not verified."},"failed_step_key":{"type":["string","null"],"description":"The `key` of the step the run stopped at, matching one of `steps[].key`. Null when nothing reached a step.","example":"welcome"},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","status","failure_reason","failure_message","failed_step_key","started_at","completed_at","created_at"],"additionalProperties":false},"AutomationRun":{"type":"object","properties":{"object":{"type":"string","enum":["automation_run"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e02"},"status":{"type":"string","enum":["running","completed","failed","cancelled"]},"failure_reason":{"type":["string","null"],"description":"Why the run ended, as a stable code, for a run that failed or was cancelled: the same value the `automation.run.failed` webhook carries. Null while it is still running and on one that completed.","example":"validation_error"},"failure_message":{"type":["string","null"],"description":"The same ending in a sentence, for a person to read. Null whenever `failure_reason` is.","example":"The domain is not verified."},"failed_step_key":{"type":["string","null"],"description":"The `key` of the step the run stopped at, matching one of `steps[].key`. Null when nothing reached a step.","example":"welcome"},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/AutomationRunStep"}}},"required":["object","id","status","failure_reason","failure_message","failed_step_key","started_at","completed_at","created_at","steps"],"additionalProperties":false},"AutomationRunStep":{"type":"object","properties":{"key":{"type":"string","example":"welcome"},"type":{"type":"string","enum":["trigger","send_email","delay","condition","contact_update","add_to_segment","topic_update"]},"status":{"type":"string","example":"completed"},"started_at":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"output":{"type":["object","null"],"additionalProperties":{},"description":"The output produced by the step, if any."},"error":{"type":["object","null"],"additionalProperties":{},"description":"The error produced by the step, if any."},"created_at":{"type":"string"}},"required":["key","type","status","started_at","completed_at","output","error","created_at"],"additionalProperties":false},"CreateEventResponse":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f01"}},"required":["object","id"],"additionalProperties":false},"CreateEventRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"trial.started","description":"The name of the event: lower-case letters, digits, `.`, `_` and `-`, starting with a letter. The reserved `rasket:` prefix belongs to the platform's own triggers and is refused."},"schema":{"type":["object","null"],"additionalProperties":{},"example":{"plan":"string","seats":"number"},"description":"A flat key/type map defining the event payload schema. Supported types are `string`, `number`, `boolean`, `date`."}},"required":["name"]},"ListEventsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/EventSummary"}}},"required":["object","has_more","data"],"additionalProperties":false},"EventSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f01"},"name":{"type":"string","example":"trial.started"},"schema":{"type":["object","null"],"additionalProperties":{"type":"string","enum":["string","number","boolean","date"]},"example":{"plan":"string","seats":"number"},"description":"A flat key/type map defining the event payload schema. Supported types are `string`, `number`, `boolean`, `date`."},"created_at":{"type":"string"},"updated_at":{"type":["string","null"]}},"required":["id","name","schema","created_at","updated_at"],"additionalProperties":false},"SendEventResponse":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"event":{"type":"string","example":"trial.started","description":"The name of the event that was sent."}},"required":["object","event"],"additionalProperties":false},"SendEventRequest":{"type":"object","properties":{"event":{"type":"string","example":"trial.started","description":"The name of the event to send."},"contact_id":{"type":"string","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f02","description":"The contact to associate with this event. Exactly one of `contact_id` or `email` must be provided."},"email":{"type":"string","example":"hello@example.com","description":"The email address to associate with this event. Exactly one of `contact_id` or `email` must be provided."},"payload":{"type":"object","additionalProperties":{},"description":"Key/value pairs to carry with the event. At most 16 KB of JSON."}},"required":["event"]},"Event":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f01"},"name":{"type":"string","example":"trial.started"},"schema":{"type":["object","null"],"additionalProperties":{"type":"string","enum":["string","number","boolean","date"]},"example":{"plan":"string","seats":"number"},"description":"A flat key/type map defining the event payload schema. Supported types are `string`, `number`, `boolean`, `date`."},"created_at":{"type":"string"},"updated_at":{"type":["string","null"]}},"required":["object","id","name","schema","created_at","updated_at"],"additionalProperties":false},"UpdateEventResponse":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f01"}},"required":["object","id"],"additionalProperties":false},"UpdateEventRequest":{"type":"object","properties":{"schema":{"type":["object","null"],"additionalProperties":{},"example":{"plan":"string","seats":"number"},"description":"A flat key/type map defining the event payload schema. Supported types are `string`, `number`, `boolean`, `date`. Set to `null` to clear it."}},"required":["schema"]},"RemoveEventResponse":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5f01"},"deleted":{"type":"boolean","enum":[true]}},"required":["object","id","deleted"],"additionalProperties":false},"RegisteredClient":{"type":"object","properties":{"client_id":{"type":"string","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"client_id_issued_at":{"type":"integer","description":"Seconds since the epoch."},"registration_client_uri":{"type":"string"},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"scope":{"type":"string"},"client_uri":{"type":"string"},"logo_uri":{"type":"string"},"software_id":{"type":"string"},"software_version":{"type":"string"},"registration_access_token":{"type":"string","description":"Shown exactly once. Required by the RFC 7592 management routes."}},"required":["client_id","client_id_issued_at","registration_client_uri","client_name","redirect_uris","grant_types","response_types","token_endpoint_auth_method","registration_access_token"],"additionalProperties":false},"OAuthRegistrationError":{"type":"object","properties":{"error":{"type":"string","enum":["invalid_client_metadata","invalid_redirect_uri","invalid_token"]},"error_description":{"type":"string"}},"required":["error","error_description"],"additionalProperties":false},"OAuthClientInformation":{"type":"object","properties":{"client_id":{"type":"string","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"client_id_issued_at":{"type":"integer","description":"Seconds since the epoch."},"registration_client_uri":{"type":"string"},"client_name":{"type":"string"},"redirect_uris":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"scope":{"type":"string"},"client_uri":{"type":"string"},"logo_uri":{"type":"string"},"software_id":{"type":"string"},"software_version":{"type":"string"}},"required":["client_id","client_id_issued_at","registration_client_uri","client_name","redirect_uris","grant_types","response_types","token_endpoint_auth_method"],"additionalProperties":false},"ListOAuthGrantsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/OAuthGrant"}}},"required":["object","has_more","data"],"additionalProperties":false},"OAuthGrant":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"client_id":{"type":"string","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"scopes":{"type":"array","items":{"type":"string"},"example":["emails:send","logs:read"]},"created_at":{"type":"string"},"revoked_at":{"type":["string","null"]},"revoked_reason":{"type":["string","null"]},"client":{"type":"object","properties":{"name":{"type":"string","example":"Acme CRM"},"logo_uri":{"type":["string","null"]}},"required":["name","logo_uri"],"additionalProperties":false}},"required":["id","client_id","scopes","created_at","revoked_at","revoked_reason","client"],"additionalProperties":false},"RevokeOAuthGrantResponse":{"type":"object","properties":{"object":{"type":"string","enum":["oauth_grant"]},"id":{"type":"string","format":"uuid","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"revoked_at":{"type":"string"},"revoked_reason":{"type":"string","example":"user"}},"required":["object","id","revoked_at","revoked_reason"],"additionalProperties":false},"TeamProfile":{"type":"object","properties":{"object":{"type":"string","enum":["team"]},"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"created_at":{"type":"string"},"risk_state":{"type":"string"},"plan":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"limits":{"type":"object","properties":{"included_emails":{"type":"integer"},"daily_cap":{"type":["integer","null"]},"domain_limit":{"type":"integer"},"webhook_endpoint_limit":{"type":"integer"},"retention_days":{"type":"integer"}},"required":["included_emails","daily_cap","domain_limit","webhook_endpoint_limit","retention_days"],"additionalProperties":false}},"required":["code","name","limits"],"additionalProperties":false},"sender_identity":{"type":"object","properties":{"sender_name":{"type":["string","null"]},"postal_address":{"$ref":"#/components/schemas/PostalAddress"}},"required":["sender_name","postal_address"],"additionalProperties":false},"ai_assist_enabled":{"type":"boolean"},"brand_kit":{"$ref":"#/components/schemas/BrandKit"},"sending":{"type":"object","properties":{"sandbox_regions":{"type":"array","items":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"]},"description":"Regions still in our sending sandbox. Mail from them only goes to verified identities, addresses on a domain verified in Rasket, and the mailbox simulator. Any other recipient gets 403 validation_error. The list is empty when no region is in the sandbox. The platform operator takes a region out of the sandbox."},"tier":{"type":"integer","description":"The rung of the sending ladder this team holds, 0 to 3. It bounds how much mail the team may send a day and a month, together with the plan: the lower of the two applies.","example":1},"tier_name":{"type":"string","description":"The rung's name: new, verified, paid or trusted.","example":"verified"},"next_unlock":{"type":["string","null"],"enum":["verify_domain","add_payment_method","operator_review",null],"description":"The one thing this team can do to reach the next rung. `verify_domain`: verify a domain you control. `add_payment_method`: add a payment method. `operator_review`: we are looking at this account, and nothing you do moves it until we are done. `null` when there is nothing to do — the team is as high as the ladder climbs on its own, or what holds it back is not an action.","example":"add_payment_method"}},"required":["sandbox_regions","tier","tier_name","next_unlock"],"additionalProperties":false,"description":"The platform's sending state as it applies to this team."},"sso":{"type":["object","null"],"properties":{"status":{"type":"string"},"issuer":{"type":"string"},"client_id":{"type":"string"},"enforced":{"type":"boolean"},"domains":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"status":{"type":"string","enum":["verified","pending"]}},"required":["domain","status"],"additionalProperties":false}}},"required":["status","issuer","client_id","enforced","domains"],"additionalProperties":false,"description":"The single sign-on summary, or null before a connection exists. Never the client secret."}},"required":["object","id","name","slug","created_at","risk_state","plan","sender_identity","ai_assist_enabled","brand_kit","sending","sso"],"additionalProperties":false},"PostalAddress":{"type":["object","null"],"properties":{"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"postal_code":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2, upper-case.","example":"US"}},"required":["line1","city","postal_code","country"],"additionalProperties":false},"BrandKit":{"type":"object","properties":{"logo_url":{"type":["string","null"],"description":"An https URL to the wide logo your emails show, on a host a mail client can reach. It is what `{{brand.logo_url}}` resolves to. At most 512 characters, and it may not contain a quote, an angle bracket, a brace or whitespace.","example":"https://cdn.example.com/acme/logo.png"},"primary_color":{"type":["string","null"],"description":"A six-digit hex colour, such as #1a73e8.","example":"#1a73e8"},"accent_color":{"type":["string","null"],"description":"A six-digit hex colour, such as #f59e0b.","example":"#f59e0b"},"font":{"type":["string","null"],"enum":["system","helvetica","arial","verdana","georgia","times","courier",null],"description":"The font family your emails use, as a key rather than a CSS string: system, helvetica, arial, verdana, georgia, times or courier. `{{brand.font}}` resolves it to a stack mail clients have.","example":"system"},"button_style":{"type":["string","null"],"enum":["square","rounded","pill",null],"description":"How your buttons are shaped: square, rounded or pill. `{{brand.button_radius}}` resolves it to the matching CSS length.","example":"rounded"},"company_name":{"type":["string","null"],"description":"One line, at most 120 characters.","example":"Acme, Inc."},"address":{"type":["string","null"],"description":"One line, at most 300 characters.","example":"500 Market Street, San Francisco, CA 94105"},"footer_text":{"type":["string","null"],"description":"One line, at most 300 characters.","example":"You are receiving this because you have an Acme account."}},"required":["logo_url","primary_color","accent_color","font","button_style","company_name","address","footer_text"],"additionalProperties":false,"description":"The design your templates wear. Every field is null until you save one, and a field left null renders as our neutral default rather than as visible text. These are set once for the project; they are never sent per email."},"PatchTeamRequest":{"type":"object","properties":{"name":{"type":"string","description":"The team's display name. Trimmed, one line, 1 to 80 characters, and not unique — two teams may share one. The team's web address is set when the team is created and a rename does not change it. Admin only: a `full_access` key may send it, an OAuth token may not.","example":"Acme Billing"},"sender_name":{"type":"string","description":"One line, at most 200 characters."},"postal_address":{"allOf":[{"$ref":"#/components/schemas/PostalAddress"},{"description":"The address every broadcast footer prints (A66). Sent alone, it is paired with the stored `sender_name`."}]},"ai_assist_enabled":{"type":"boolean","description":"Turning AI assist on sends the content you ask about to Anthropic; recipient addresses are never included."},"brand_kit":{"allOf":[{"$ref":"#/components/schemas/BrandKit"},{"description":"The whole brand kit, not a patch of it: every field is required and a field you send as null goes back to our default. Read it from `GET /team`, change what you want and send it back. These values fill `{{brand.…}}` in your templates and are never per-email data."}]}},"additionalProperties":{}},"DomainRecords":{"type":"object","properties":{"object":{"type":"string","enum":["domain_records"]},"domain_id":{"type":"string","format":"uuid"},"sending_verified":{"type":"boolean"},"tracking_verified":{"type":"boolean"},"receiving_verified":{"type":"boolean"},"receiving_host":{"type":"string","description":"Where the domain receives mail: `@` for the domain itself, or a DNS label such as `inbound`."},"receiving_address":{"type":["string","null"],"description":"`anything@<receiving hostname>` while receiving is on and the Receiving MX is verified, else null."},"records":{"type":"array","items":{"$ref":"#/components/schemas/DomainRecordObservation"}}},"required":["object","domain_id","sending_verified","tracking_verified","receiving_verified","receiving_host","receiving_address","records"],"additionalProperties":false},"DomainRecordObservation":{"type":"object","properties":{"record":{"type":"string","enum":["SPF","DKIM","Receiving","Tracking","TrackingCAA","BIMI"]},"name":{"type":"string"},"type":{"type":"string","enum":["MX","TXT","CNAME","CAA"]},"ttl":{"type":"string"},"value":{"type":"string","description":"What to publish."},"priority":{"type":"integer"},"status":{"type":"string","enum":["pending","verified","failed","temporary_failure","not_started"]},"observed":{"type":"array","items":{"type":"string"},"description":"What DNS answered at `name` on the last check."},"reason":{"type":["string","null"],"description":"Why the record is not verified, such as `not_found` or `value_mismatch`."},"last_checked_at":{"type":["string","null"]}},"required":["record","name","type","ttl","value","status","observed","reason","last_checked_at"],"additionalProperties":false},"EmailEventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailEvent"}}},"required":["object","has_more","data"],"additionalProperties":false},"EmailEvent":{"type":"object","properties":{"object":{"type":"string","enum":["email_event"]},"id":{"type":"string","format":"uuid"},"type":{"type":"string","example":"email.delivered"},"recipient":{"type":["string","null"],"description":"The address this event is about, or null for the whole message."},"occurred_at":{"type":"string"},"data":{"description":"The event-specific object in webhook shape, stored as it arrived."}},"required":["object","id","type","recipient","occurred_at"],"additionalProperties":false},"AiSubjectSuggestions":{"type":"object","properties":{"object":{"type":"string","enum":["ai_subject_suggestions"]},"suggestions":{"type":"array","items":{"type":"string"}},"credits_remaining":{"type":"integer"},"credits":{"$ref":"#/components/schemas/AiCredits"}},"required":["object","suggestions","credits_remaining","credits"],"additionalProperties":false},"AiCredits":{"type":"object","properties":{"limit":{"type":"integer"},"used":{"type":"integer"},"remaining":{"type":"integer"}},"required":["limit","used","remaining"],"additionalProperties":false},"AiSubjectLinesRequest":{"type":"object","properties":{"subject":{"type":"string","description":"The current subject, if any."},"html":{"type":"string","description":"The HTML body, up to 100000 characters."},"text":{"type":"string","description":"The plain-text body, up to 100000 characters."},"audience":{"type":"string","description":"Who the email is for, up to 2000 characters."},"template_id":{"type":"string","format":"uuid","description":"The template this call is about, recorded as the request's target. It must be one of this team's templates; the content itself comes from the body, not from the saved template."}}},"AiDraft":{"type":"object","properties":{"object":{"type":"string","enum":["ai_draft"]},"html":{"type":"string"},"text":{"type":"string"},"credits_remaining":{"type":"integer"},"credits":{"$ref":"#/components/schemas/AiCredits"}},"required":["object","html","text","credits_remaining","credits"],"additionalProperties":false},"AiDraftRequest":{"type":"object","properties":{"brief":{"type":"string","description":"What the email should say, up to 2000 characters.","example":"Welcome a new customer and point them at the quickstart."},"tone":{"type":"string","enum":["neutral","friendly","formal"]},"existing_html":{"type":"string","description":"A draft to rework, up to 100000 characters."},"template_id":{"type":"string","format":"uuid","description":"The template this call is about, recorded as the request's target. It must be one of this team's templates; the content itself comes from the body, not from the saved template."}},"required":["brief"]},"AiDiagnosis":{"type":"object","properties":{"object":{"type":"string","enum":["ai_diagnosis"]},"summary":{"type":"string"},"likely_causes":{"type":"array","items":{"type":"string"}},"next_steps":{"type":"array","items":{"type":"string"}},"cause":{"type":["string","null"],"enum":["provider_failure",null],"description":"`provider_failure` when the email failed on our mail servers' side: the answer quotes the recorded reason and costs nothing. Null for an answer from the assistant."},"created_at":{"type":"string"},"stored":{"type":"boolean","description":"True when this diagnosis was made earlier for the same state of the email and read back. A stored answer costs nothing, and neither does a `provider_failure` answer."},"credits_remaining":{"type":"integer"},"credits":{"$ref":"#/components/schemas/AiCredits"}},"required":["object","summary","likely_causes","next_steps","cause","created_at","stored","credits_remaining","credits"],"additionalProperties":false},"LimitRequestList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/LimitRequest"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"],"additionalProperties":false},"LimitRequest":{"type":"object","properties":{"object":{"type":"string","enum":["limit_request"]},"id":{"type":"string"},"status":{"type":"string","enum":["approved","pending","declined"]},"requested_daily":{"type":["integer","null"]},"requested_monthly":{"type":["integer","null"]},"expected_volume":{"type":["integer","null"]},"use_case":{"type":"string"},"granted_daily":{"type":["integer","null"]},"granted_monthly":{"type":["integer","null"]},"decision_reason":{"type":["string","null"]},"decided_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["object","id","status","requested_daily","requested_monthly","expected_volume","use_case","granted_daily","granted_monthly","decision_reason","decided_at","created_at"],"additionalProperties":false},"LimitRequestCreate":{"type":"object","properties":{"requested_daily":{"type":"integer","description":"The daily limit you would like, in emails a day."},"requested_monthly":{"type":"integer","description":"The monthly limit you would like. Always reviewed by a person: a monthly allowance is part of the plan."},"expected_volume":{"type":"integer","description":"Emails a month you expect to send at peak."},"use_case":{"type":"string","maxLength":1000,"description":"What this project sends and why it needs more room."}},"required":["use_case"]},"BrandKitUpload":{"type":"object","properties":{"object":{"type":"string","enum":["brand_kit_upload"]},"url":{"type":"string","description":"The stable HTTPS URL the file is served at. Send it as `brand_kit.logo_url` in `PATCH /team` to use it.","example":"https://share.rasket.com/brand-kit/0199c4a2-7b1e-7d30-8f2a-4c6e9b1d3a50/9d3c5d18b976973c1b6e4bcc0d7d3dfc76db4a69ccdb9aaebbc78e919d623909.png"},"content_type":{"type":"string","enum":["image/png","image/jpeg","image/svg+xml"]},"bytes":{"type":"integer","description":"Size of the hosted file."},"sha256":{"type":"string","description":"SHA-256 of the hosted bytes, 64 lowercase hex characters."},"width":{"type":["integer","null"],"description":"Width in pixels of a PNG or JPG; null for an SVG."},"height":{"type":["integer","null"],"description":"Height in pixels of a PNG or JPG; null for an SVG."}},"required":["object","url","content_type","bytes","sha256","width","height"],"additionalProperties":false}},"parameters":{},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key (rk_…) or an OAuth access token (rko_…). Send a User-Agent."},"sessionCookie":{"type":"apiKey","in":"cookie","name":"rsk_session","description":"The dashboard session cookie. Session-only routes accept nothing else."},"registrationAccessToken":{"type":"http","scheme":"bearer","description":"The `registration_access_token` `POST /oauth/register` returned once (RFC 7592). It manages that one client and nothing else."}}},"paths":{"/api/healthz":{"get":{"tags":["operations"],"summary":"The deployment is serving","responses":{"200":{"description":"Serving.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/readyz":{"get":{"tags":["operations"],"summary":"Every dependency is usable","responses":{"200":{"description":"Ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ready"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"One or more checks failed; `failed` names them.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ready"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/signup":{"post":{"tags":["auth"],"summary":"Create an account, its first team and a session","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}}},"responses":{"201":{"description":"The account, its first team and a session cookie.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/login":{"post":{"tags":["auth"],"summary":"Exchange an email and password for a session","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"The signed-in user and their current team, or — when the account has a second factor — the challenge that has to be answered before a session exists.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Session"},{"$ref":"#/components/schemas/MfaChallenge"}]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/logout":{"post":{"tags":["auth"],"summary":"Revoke this session, or every session this user has","requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutRequest"}}}},"responses":{"200":{"description":"The session is revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutResult"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/verify-email":{"post":{"tags":["auth"],"summary":"Consume a verification token","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"The address is verified.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailResult"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/request-reset":{"post":{"tags":["auth"],"summary":"Start a password reset","description":"Always answers 200 with the same body, whether or not the address has an account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}}},"responses":{"200":{"description":"The request was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetRequested"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/reset":{"post":{"tags":["auth"],"summary":"Consume a reset token and set a new password","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}}},"responses":{"200":{"description":"The password is changed and every session revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetResult"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The reset token is invalid or has expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/mfa":{"get":{"tags":["auth"],"summary":"Whether this account has a second factor, and how many recovery codes are left","responses":{"200":{"description":"The account's MFA state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaStatus"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/mfa/enroll":{"post":{"tags":["auth"],"summary":"Generate a TOTP secret and return its otpauth: URI, once","description":"The URI and the base32 secret are returned exactly once and are never logged, stored in plaintext, or derivable again. Enrolment does not turn MFA on.","responses":{"200":{"description":"The enrolment secret, for this response only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaEnrolment"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/mfa/activate":{"post":{"tags":["auth"],"summary":"Confirm the secret with a code and turn the second factor on","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaConfirmRequest"}}}},"responses":{"200":{"description":"MFA is on, and the ten recovery codes, once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaActivated"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/mfa/disable":{"post":{"tags":["auth"],"summary":"Turn the second factor off and destroy every recovery code","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaConfirmRequest"}}}},"responses":{"200":{"description":"MFA is off.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaDisabled"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/mfa/recovery-codes":{"post":{"tags":["auth"],"summary":"Replace the ten recovery codes with ten new ones","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaCodeRequest"}}}},"responses":{"200":{"description":"Ten fresh codes, once. The previous ten are gone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaRecoveryCodes"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/auth/mfa/verify":{"post":{"tags":["auth"],"summary":"Answer a login challenge with an authenticator code","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyRequest"}}}},"responses":{"200":{"description":"The signed-in user, and the session cookie.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The code or the challenge is not valid, expired, or already used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/auth/mfa/recovery":{"post":{"tags":["auth"],"summary":"Answer a login challenge with one of the ten recovery codes","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaRecoveryRequest"}}}},"responses":{"200":{"description":"The signed-in user, and the session cookie. One code spent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The code or the challenge is not valid, expired, or already used.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/me":{"get":{"tags":["auth"],"summary":"The signed-in user, their current team and every team they belong to","responses":{"200":{"description":"The signed-in user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams":{"post":{"tags":["teams"],"summary":"Create a team and become its admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamRequest"}}}},"responses":{"201":{"description":"The new team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"get":{"tags":["teams"],"summary":"Every team the signed-in user belongs to","responses":{"200":{"description":"The user's teams.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/switch":{"post":{"tags":["teams"],"summary":"Remember this team as the session's current one","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The team now selected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/members":{"get":{"tags":["teams"],"summary":"The members of a team, with their MFA state","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The team's members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/members/{member_id}":{"patch":{"tags":["teams"],"summary":"Change a member's role","description":"Admin only. The team's last admin cannot be demoted: a team with no admin can never be administered again (A151).","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000002"},"required":true,"name":"member_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetTeamMemberRoleRequest"}}}},"responses":{"200":{"description":"The team's members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"delete":{"tags":["teams"],"summary":"Remove a member from a team","description":"Admin only, and never the last admin. An admin may remove themselves while another admin remains. The removed member's sessions stop pointing at this team.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000002"},"required":true,"name":"member_id","in":"path"}],"responses":{"204":{"description":"Removed."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/invitations":{"get":{"tags":["teams"],"summary":"The open invitations to a team","description":"Admin only. Open and unexpired invitations; the token is never returned, in this or any other response.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The team's open invitations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"post":{"tags":["teams"],"summary":"Invite someone to a team","description":"Admin only. Mints a 7-day token, stores only its SHA-256 and sends the one message that carries it. A second open invitation to the same address is 409; an address that is already a member is 422.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamInvitationRequest"}}}},"responses":{"201":{"description":"The invitation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitation"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/invitations/{invitation_id}/reissue":{"post":{"tags":["teams"],"summary":"Send an invitation again","description":"Admin only. A new token and a new expiry, so the link in the first message stops working.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000001"},"required":true,"name":"invitation_id","in":"path"}],"responses":{"200":{"description":"The invitation, sent again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitation"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/invitations/{invitation_id}":{"delete":{"tags":["teams"],"summary":"Withdraw an invitation","description":"Admin only. The row is deleted, so the same address can be invited again immediately.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000001"},"required":true,"name":"invitation_id","in":"path"}],"responses":{"204":{"description":"Withdrawn."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/deletion":{"get":{"tags":["teams"],"summary":"Whether the project is scheduled for deletion","description":"Any member. `none` when nothing is scheduled.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The project's deletion state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamDeletion"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"post":{"tags":["teams"],"summary":"Schedule the project for deletion","description":"Admin only, from a signed-in session. `confirm` must be the project's name. Sending stops immediately; the data is erased 30 days later unless the deletion is canceled. Refused while the project is on a paid plan, has paid add-ons or a dedicated IP pool. A project already scheduled answers with its schedule.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamDeletionRequest"}}}},"responses":{"200":{"description":"The deletion, as now scheduled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamDeletion"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"delete":{"tags":["teams"],"summary":"Cancel the project's scheduled deletion","description":"Admin only, from a signed-in session, and only inside the grace window: once the purge has started this is `409 resource_locked`. Sending resumes at once.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The project's deletion state after the cancel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamDeletion"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/teams/{team_id}/exports":{"get":{"tags":["teams"],"summary":"The project's recent data exports","description":"Admin only, from a signed-in session. Newest first; a ready export carries a signed `download_url` until it expires.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"200":{"description":"The project's exports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamExportList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null},"post":{"tags":["teams"],"summary":"Export the project's data","description":"Admin only, from a signed-in session. Starts a background job that writes one archive of the project's data (a CSV or JSON file per resource). An export already on its way is returned instead of a second one.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"team_id","in":"path"}],"responses":{"202":{"description":"The export, queued or already running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamExport"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/invitations/accept":{"post":{"tags":["teams"],"summary":"Accept an invitation to a team","description":"Session only. The token names the team; the session must be the invited address's. The team becomes the session's current one.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptTeamInvitationRequest"}}}},"responses":{"200":{"description":"The team just joined.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Team"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request origin is not allowed, or the actor may not do this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such team, or not a member of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"sessionCookie":[]}],"x-rasket-permission":"session","x-rasket-scope":null}},"/api/v1/billing":{"get":{"tags":["billing"],"summary":"The team's plan, usage this period, payment state, add-ons and pending change","responses":{"200":{"description":"The Billing page in one object.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Billing"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"billing:read"}},"/api/v1/billing/checkout":{"post":{"tags":["billing"],"summary":"Start a subscription: a hosted Checkout session for a plan, or for an add-on","description":"Answers the hosted page to send the browser to, and when it stops working. Send exactly one of `plan_code` and `addon_code`: `plan_code` starts a subscription on that plan, and `addon_code` (`inbox_storage_100gb` or `inbox_seat`) buys that add-on on its own, leaving the team on the plan it is already on. `quantity` sets how many units the session buys and goes only with `addon_code`; it defaults to 1, and only `inbox_seat` is sold by the unit. Either way the team must not already have a subscription — one that does changes its plan with `POST /billing/plan` and buys add-ons with `POST /billing/addons`. `return_url` (absolute `https`) is where Stripe sends the browser back, with `checkout=success` or `checkout=cancelled` appended; without one, `return_to` picks the dashboard page — `plan` (the default), `inbox` or `inbox_settings`. Called with an API key, no email address is sent to the payment provider: the customer enters one on the hosted page.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan_code":{"type":"string","minLength":1,"maxLength":64},"addon_code":{"type":"string","enum":["inbox_storage_100gb","inbox_seat"]},"quantity":{"type":"integer","minimum":1,"maximum":100},"return_url":{"type":"string","minLength":1,"maxLength":2048},"return_to":{"type":"string","enum":["plan","inbox","inbox_settings"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Where to send the browser, and until when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"This plan or add-on is not available for purchase yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/portal":{"post":{"tags":["billing"],"summary":"Payment method, address, tax ID, invoices and cancellation: the Customer Portal","responses":{"200":{"description":"Where to send the browser.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalSession"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/plan":{"post":{"tags":["billing"],"summary":"Change the plan on an existing subscription","description":"An upgrade takes effect immediately with prorations; a downgrade is scheduled for the end of the current period. Free → paid is a Checkout and paid → free is a Portal cancellation, so both are refused here. A move that would turn off the team's single sign-on is refused for an API key: it decides who may sign in, so a signed-in admin makes it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan_code":{"type":"string","minLength":1,"maxLength":64}},"required":["plan_code"],"additionalProperties":false}}}},"responses":{"200":{"description":"The Billing page after the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Billing"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/invoices":{"get":{"tags":["billing"],"summary":"The team's invoices, newest first","description":"Read from the billing provider and cached for sixty seconds per team.","responses":{"200":{"description":"The invoices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingInvoiceList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"billing:read"}},"/api/v1/domains":{"post":{"tags":["domains"],"summary":"Add a sending domain and generate its DNS records","description":"Generates a 2048-bit DKIM keypair (D5) with the selector `rasket` (D6), stores the private key envelope-encrypted, and returns every record the domain must publish. All records start `not_started`; the `dns-verify` cron checks them from now on.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"],"default":"us-east-1"},"custom_return_path":{"type":"string","description":"The label the Sending records are published at. Omit it and the first free label of `rasket`, `rasketmail`, `rk`, `rasket1`, `rasket2` is chosen; a label you name that already holds another service's records is `422 invalid_parameter` with `details.reason` `return_path_in_use`."},"tracking_subdomain":{"type":"string","default":"links"},"receiving_host":{"type":"string","default":"@"},"open_tracking":{"type":"boolean","default":false},"click_tracking":{"type":"boolean","default":false},"tls":{"type":"string","enum":["opportunistic","enforced"],"default":"opportunistic"},"capabilities":{"type":"object","properties":{"sending":{"type":"string","enum":["enabled","disabled"]},"receiving":{"type":"string","enum":["enabled","disabled"]}},"additionalProperties":false},"confirm_replace_mx":{"type":"boolean","description":"Set to true to turn on receiving at a name whose MX already delivers to another mailbox provider (otherwise 409 receiving_mx_in_use)."}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"The domain and its records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDomainResponse"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name (`resource_locked`), or receiving would take the name's mail from the provider that has it today (`receiving_mx_in_use`; repeat with `confirm_replace_mx: true` or use a receiving subdomain).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"},"get":{"tags":["domains"],"summary":"List the team's domains","description":"Newest first. Filter by `search` (text in the name) and `status` (one state or several, comma-separated); both apply across every page of the cursor.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"before","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive text in the domain name. 1–200 characters after trimming."},"required":false,"description":"Case-insensitive text in the domain name. 1–200 characters after trimming.","name":"search","in":"query"},{"schema":{"type":"string","description":"Only domains in these states, comma-separated: pending, verified, failed, not_started, partially_verified, partially_failed."},"required":false,"description":"Only domains in these states, comma-separated: pending, verified, failed, not_started, partially_verified, partially_failed.","name":"status","in":"query"}],"responses":{"200":{"description":"The team's domains.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainList"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:read"}},"/api/v1/domains/claim":{"post":{"tags":["domains"],"summary":"Claim a domain another team has verified","description":"Creates a placeholder domain for your team with fresh DKIM keys and returns the TXT record that proves you control the name. The transfer runs by itself once the record resolves, unless the current owner verified within 72 hours, sent in the last 24 hours, or has scheduled mail from it. Claims expire after 7 days. Repeating the call while a claim is open returns that claim unchanged with `200`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"region":{"type":"string","enum":["us-east-1","eu-west-1","sa-east-1","ap-northeast-1"],"default":"us-east-1"},"custom_return_path":{"type":"string","description":"The label the Sending records are published at. Omit it and the first free label of `rasket`, `rasketmail`, `rk`, `rasket1`, `rasket2` is chosen; a label you name that already holds another service's records is `422 invalid_parameter` with `details.reason` `return_path_in_use`."},"tracking_subdomain":{"type":"string","default":"links"},"receiving_host":{"type":"string","default":"@"},"open_tracking":{"type":"boolean","default":false},"click_tracking":{"type":"boolean","default":false},"tls":{"type":"string","enum":["opportunistic","enforced"],"default":"opportunistic"},"capabilities":{"type":"object","properties":{"sending":{"type":"string","enum":["enabled","disabled"]},"receiving":{"type":"string","enum":["enabled","disabled"]}},"additionalProperties":false},"confirm_replace_mx":{"type":"boolean","description":"Set to true to turn on receiving at a name whose MX already delivers to another mailbox provider (otherwise 409 receiving_mx_in_use)."}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"An open claim already existed and is returned unchanged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainClaim"}}}},"201":{"description":"The claim and the record to publish.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainClaim"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/claim":{"get":{"tags":["domains"],"summary":"The latest claim for a domain","description":"`domain_id` is the placeholder domain the claim created, not the claim's own id.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The latest claim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainClaim"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:read"}},"/api/v1/domains/{domain_id}/claim/verify":{"post":{"tags":["domains"],"summary":"Check a claim's ownership TXT record","description":"Asks for the claim to be looked at sooner. The claim stays `pending` while the check runs, so poll this domain's claim for the result. Rate-limited to one call per minute per domain, shared with Verify a domain.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The claim as it stands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainClaim"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}":{"get":{"tags":["domains"],"summary":"One domain, with the current status of every record","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:read"},"patch":{"tags":["domains"],"summary":"Change tracking, TLS, capabilities, the tracking subdomain or the return path","description":"`region` is chosen at creation and is refused here with `422 invalid_parameter` (05 §1). A new `custom_return_path` moves the Sending records to that label: they go back to `pending` and are checked again there, DKIM is unchanged, and a domain that could send keeps sending while you publish them. Keep the old records until the new ones verify. A label that already holds another service's records is `422 invalid_parameter` with `details.reason` `return_path_in_use`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"open_tracking":{"type":"boolean"},"click_tracking":{"type":"boolean"},"tls":{"type":"string","enum":["opportunistic","enforced"]},"tracking_subdomain":{"type":"string"},"receiving_host":{"type":"string"},"capabilities":{"type":"object","properties":{"sending":{"type":"string","enum":["enabled","disabled"]},"receiving":{"type":"string","enum":["enabled","disabled"]}},"additionalProperties":false},"custom_return_path":{"type":"string"},"confirm_replace_mx":{"type":"boolean","description":"Set to true to turn on receiving at a name whose MX already delivers to another mailbox provider (otherwise 409 receiving_mx_in_use)."},"region":{"description":"Chosen at creation and immutable (05 §1); sending it is 422 invalid_parameter."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The updated domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRef"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Receiving would take the name's mail from the provider that has it today (`receiving_mx_in_use`; repeat with `confirm_replace_mx: true` or use a receiving subdomain), or the domain changed while it was being checked (`resource_locked`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"},"delete":{"tags":["domains"],"summary":"Delete a domain","description":"Soft delete: the row is retained for 30 days for audit and purged with its DKIM ciphertext by the retention cron (05 §11). Scheduled sends from the domain are canceled and API keys restricted to it are suspended.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDomainResponse"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/verify":{"post":{"tags":["domains"],"summary":"Check this domain's DNS records now","description":"Runs the check immediately, waiting up to 10 seconds, and returns the domain with each record's status. A second call within 15 seconds returns the current state without checking again. If a check is already running or does not finish in time, you get the current state and the scheduled check finishes it.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The domain, with each record's status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyDomainResponse"}}}},"400":{"description":"Validation failed, or a capability is unavailable in this region.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another team has verified this name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a claim was checked less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/dkim/regenerate":{"post":{"tags":["domains"],"summary":"Generate a new DKIM keypair for this domain","description":"Mints a fresh RSA keypair at `key_bits` (2048 by default, 1024 for a DNS panel that refuses a ~392-character TXT value), stores the private key encrypted and returns the DKIM record with its new `p=` value. The domain stops being verified for sending until we see the new record, so publish it before the next send. Refused with 429 within a minute of the last regenerate, verify, auto-configure or claim check on this domain.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key_bits":{"type":"number","description":"The RSA modulus size: 2048 (the default) or 1024 (D5's shorter-key fallback)."}},"required":["key_bits"],"additionalProperties":false}}}},"responses":{"200":{"description":"The domain, with the DKIM record's new value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A verification run is already in progress for this domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"`key_bits` is missing, or is not 1024 or 2048.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or a key was regenerated for this domain less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/autoconfigure":{"post":{"tags":["domains"],"summary":"Publish this domain's DNS records through its provider","description":"Writes the records for every capability this domain has enabled into the customer's Cloudflare zone, using an API token scoped to `Zone → DNS → Edit` for that one zone. Records we did not write are never touched: an existing record at one of our names is reported in `conflicts` rather than overwritten, and nothing is ever deleted. The token is encrypted at rest and deleted as soon as the records are written unless `keep_token` is `true`. On success the affected records move to `pending` and verification runs immediately. Rate-limited to one call per minute per domain, shared with `POST /domains/{domain_id}/verify`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["cloudflare"],"description":"The DNS provider to configure. `cloudflare` is the only one V1 automates (05 §8)."},"token":{"type":"string","minLength":1,"description":"A Cloudflare API token scoped to `Zone → DNS → Edit` for this domain's zone, and that zone only. Global API keys are refused."},"keep_token":{"type":"boolean","default":false,"description":"`true` to keep the token as a revocable credential for re-applying records later. Left `false`, it is deleted as soon as the records are written."}},"required":["provider","token"],"additionalProperties":false}}}},"responses":{"200":{"description":"What was created, updated and left alone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoconfigureResponse"}}}},"400":{"description":"The token was refused: invalid, a Global API key, or not scoped to this one zone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team, or no stored credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A verification run is already in progress for this domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or auto-configuration was requested less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Cloudflare could not be reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/autoconfigure/credential":{"delete":{"tags":["domains"],"summary":"Revoke the stored DNS provider credential","description":"Deletes the provider token kept for this domain. Records already published are left exactly as they are; only our copy of the credential goes away. Revoke the token at your provider as well — deleting it here stops us using it, not anyone else.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The credential was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteCredentialResponse"}}}},"400":{"description":"The token was refused: invalid, a Global API key, or not scoped to this one zone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team, or no stored credential.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"A verification run is already in progress for this domain.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests, or auto-configuration was requested less than a minute ago.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Cloudflare could not be reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/logo":{"post":{"tags":["domains"],"summary":"Upload this domain's brand logo","description":"Stores an SVG as the domain's brand logo and returns the stable HTTPS URL it is served at. The file must be a square SVG Tiny Portable/Secure document — the profile mail apps accept — and anything else is refused with one reason per rule it breaks; nothing is repaired or stripped on the way in. Uploading again replaces the logo and changes the URL, because the URL carries the digest of the bytes it serves. The logo is shown next to your mail in the apps that support it once `default._bimi` is published and the domain's DMARC policy is at enforcement.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"svg":{"type":"string","minLength":1,"maxLength":32768,"description":"The logo, as SVG source. It must be a square SVG Tiny Portable/Secure file: no script, no event handlers, no embedded images, no external references, a `<title>`, `baseProfile=\"tiny-ps\"` and `version=\"1.2\"`. Anything else is refused with a reason per rule it breaks."}},"required":["svg"],"additionalProperties":false}}}},"responses":{"200":{"description":"The stored logo and the URL it is served at.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBrandLogo"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The file is not an SVG that may be published as a brand logo, and `errors` carries one entry per rule it breaks. Also the managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a logo, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"},"delete":{"tags":["domains"],"summary":"Remove this domain's brand logo","description":"Deletes the stored logo and the URL it was served at. A domain with no logo answers the same way, so this is safe to call twice. Publishing stops when the `default._bimi` record is next generated; until then the record points at a URL that no longer answers.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The logo is gone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDomainBrandLogoResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The file is not an SVG that may be published as a brand logo, and `errors` carries one entry per rule it breaks. Also the managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a logo, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/domains/{domain_id}/logo/certificate":{"get":{"tags":["domains"],"summary":"Read this domain's brand certificate","description":"Returns where the domain's brand certificate has got to. `state` is `none` before anything is asked for, `awaiting_certificate` once a signing request exists, `active` while a certificate is installed and published, `logo_changed` when the logo has been replaced since the certificate was issued, and `expired` once it is past its end date. `published` is true only for `active`, and is what decides whether `default._bimi` carries an `a=` tag.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The certificate, and what to do about it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBrandCertificate"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a certificate, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:read"},"post":{"tags":["domains"],"summary":"Create a certificate signing request","description":"Generates a key pair for this domain and returns the certificate signing request to give to a certificate authority. You buy the certificate from them; we never see the transaction and charge nothing for it. The private key stays here, encrypted, and is never returned by any endpoint. Calling this again while a request is open returns the same request rather than a new one, because the open one may already be with the authority — to start over, delete the certificate first. The domain needs a brand logo, because a certificate is issued for the logo it will be published with.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"common_name":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^<>\"'`,+=\\\\;#]+$","description":"The domain the logo is published for, such as `mail.example.com`."},"organization":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^<>\"'`,+=\\\\;#]+$","description":"Your organisation's legal name, exactly as it is registered. The authority checks this."},"organizational_unit":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^<>\"'`,+=\\\\;#]+$","description":"An optional division within the organisation."},"locality":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^<>\"'`,+=\\\\;#]+$","description":"The city or town the organisation is registered in."},"state":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[^<>\"'`,+=\\\\;#]+$","description":"The state, province or region."},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"The two-letter country code, such as `US`."}},"required":["common_name","organization","locality","state","country"],"additionalProperties":false}}}},"responses":{"200":{"description":"The signing request, and the details it carries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBrandCertificate"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, the User-Agent header is absent, or this team's plan does not include a brand certificate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could not be built, or the certificate cannot be published for this domain, and `errors` carries one entry per reason. Also the managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a certificate, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"},"patch":{"tags":["domains"],"summary":"Install the issued certificate","description":"Stores the certificate chain the authority issued and publishes its URL as the `a=` tag of `default._bimi`. The chain is accepted only if its first certificate carries the public key of this domain's signing request, it is inside its validity window, and each certificate is signed by the one after it — so a certificate belonging to somebody else is refused however genuine it is. Send only certificates, never a private key. Publish the `default._bimi` record again after this: its value has changed.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pem":{"type":"string","minLength":1,"maxLength":131072,"description":"The certificate chain the authority issued, PEM-encoded: your certificate first, then each one that issued the one above it. Never a private key."}},"required":["pem"],"additionalProperties":false}}}},"responses":{"200":{"description":"The installed certificate and the URL it is at.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainBrandCertificate"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, the User-Agent header is absent, or this team's plan does not include a brand certificate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request could not be built, or the certificate cannot be published for this domain, and `errors` carries one entry per reason. Also the managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a certificate, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"},"delete":{"tags":["domains"],"summary":"Remove this domain's brand certificate","description":"Deletes the signing request, its key and the installed certificate, and puts `default._bimi` back to the self-asserted value it had before — the logo is untouched. A domain with no certificate answers the same way, so this is safe to call twice. Publish the `default._bimi` record again afterwards.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The certificate is gone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDomainBrandCertificateResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unusable API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This key may not manage domains, or the User-Agent header is absent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such domain in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The managed address, which publishes no records of its own.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a certificate, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:write"}},"/api/v1/api-keys":{"post":{"tags":["api-keys"],"summary":"Create an API key and return its token once","description":"The `token` is shown exactly once and is never recoverable; only its SHA-256 hash and the `rk_` prefix are stored. `domain_id` is accepted only with `sending_access`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"permission":{"type":"string","enum":["full_access","sending_access"],"default":"full_access"},"domain_id":{"type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"The new key and its token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null},"get":{"tags":["api-keys"],"summary":"List the team's API keys","description":"Newest first. Three additive filters: `status` (`active`, the default, means not revoked; `revoked`; `all`), `search` (a case-insensitive substring of the name; `%` and `_` match literally) and `permission` (`full_access` or `sending_access`).","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"before","in":"query"},{"schema":{"type":"string","enum":["active","revoked","all"],"default":"active"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["full_access","sending_access"]},"required":false,"name":"permission","in":"query"}],"responses":{"200":{"description":"A page of API keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/api-keys/{api_key_id}":{"patch":{"tags":["api-keys"],"summary":"Rename an API key","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"api_key_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"The renamed key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null},"delete":{"tags":["api-keys"],"summary":"Revoke an API key","description":"Revocation is terminal and idempotent. The row is kept with `status = revoked` so request logs and emails keep their join; it is never deleted.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"018f4c1e-0000-7000-8000-000000000000"},"required":true,"name":"api_key_id","in":"path"}],"responses":{"200":{"description":"The revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteApiKeyResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/suppressions/batch/add":{"post":{"tags":["suppressions"],"summary":"Add up to 100 suppressions at once","description":"All-or-nothing: one malformed address rejects the request and writes nothing. Addresses already suppressed come back with their existing ids and are not re-added.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAddSuppressionsRequest"}}}},"responses":{"201":{"description":"The suppressions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedSuppressionList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:write"}},"/api/v1/suppressions/batch/remove":{"post":{"tags":["suppressions"],"summary":"Remove up to 100 suppressions at once","description":"Takes `emails` or `ids`, never both. An entry that was not suppressed is reported with `deleted: false` rather than failing the batch.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchRemoveSuppressionsRequest"}}}},"responses":{"200":{"description":"The removals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovedSuppressionList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:write"}},"/api/v1/suppressions":{"post":{"tags":["suppressions"],"summary":"Suppress an email address","description":"Origin `manual`. An address that is already suppressed keeps its earliest row and its origin, and the existing id is returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSuppressionRequest"}}}},"responses":{"201":{"description":"The suppression.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedSuppression"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:write"},"get":{"tags":["suppressions"],"summary":"List suppressions","parameters":[{"schema":{"type":"string","enum":["bounce","complaint","manual","unsubscribe"],"description":"Filter by origin."},"required":false,"description":"Filter by origin.","name":"origin","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive substring of the address. `%` and `_` match literally."},"required":false,"description":"Case-insensitive substring of the address. `%` and `_` match literally.","name":"search","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Suppressions added before this are excluded."},"required":false,"description":"ISO 8601, inclusive. Suppressions added before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Suppressions added after this are excluded."},"required":false,"description":"ISO 8601, inclusive. Suppressions added after this are excluded.","name":"end_date","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:read"}},"/api/v1/suppressions/{suppression}":{"get":{"tags":["suppressions"],"summary":"Retrieve a suppression by ID or email address","parameters":[{"schema":{"type":"string","description":"The suppression ID or the email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The suppression ID or the email address.","name":"suppression","in":"path"}],"responses":{"200":{"description":"The suppression.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:read"},"delete":{"tags":["suppressions"],"summary":"Remove a suppression by ID or email address","parameters":[{"schema":{"type":"string","description":"The suppression ID or the email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The suppression ID or the email address.","name":"suppression","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemovedSuppression"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key, or a sending-only key on a non-sending endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the User-Agent header is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such suppression in this team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A parameter or field is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"suppressions:write"}},"/api/v1/webhooks":{"post":{"tags":["webhooks"],"summary":"Create a webhook endpoint and return its signing secret once","description":"The `signing_secret` is shown exactly once and is never recoverable; afterwards it is masked. The endpoint count is limited by your plan.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]},"minItems":1}},"required":["endpoint","events"],"additionalProperties":false}}}},"responses":{"201":{"description":"The new endpoint and its signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSecret"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"},"get":{"tags":["webhooks"],"summary":"List the team's webhook endpoints","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"before","in":"query"}],"responses":{"200":{"description":"A page of endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"}},"/api/v1/webhooks/{webhook_id}/rotate-secret":{"post":{"tags":["webhooks"],"summary":"Rotate the signing secret, keeping the previous one valid for 24 hours","description":"During the overlap every delivery is signed with both secrets and `svix-signature` carries two `v1,` values; a verifier that knows either one accepts the delivery.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The new signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSecret"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"}},"/api/v1/webhooks/{webhook_id}/events/{event_id}/replay":{"post":{"tags":["webhooks"],"summary":"Deliver one event again","description":"The same bytes under the same `svix-id`, with a fresh timestamp and signature. A manual replay delivers once and schedules no automatic retries. Limited to 10 per minute.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128,"example":"msg_0198f4c1000070008000000000000000"},"required":true,"name":"event_id","in":"path"}],"responses":{"200":{"description":"The replayed event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventRef"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"}},"/api/v1/webhooks/{webhook_id}/events/{event_id}/attempts":{"get":{"tags":["webhooks"],"summary":"List every delivery attempt made for one event","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128,"example":"msg_0198f4c1000070008000000000000000"},"required":true,"name":"event_id","in":"path"}],"responses":{"200":{"description":"The attempts, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookAttemptList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"}},"/api/v1/webhooks/{webhook_id}/events/{event_id}":{"get":{"tags":["webhooks"],"summary":"Read one event, with its payload and its schedule","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128,"example":"msg_0198f4c1000070008000000000000000"},"required":true,"name":"event_id","in":"path"}],"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"}},"/api/v1/webhooks/{webhook_id}/events":{"get":{"tags":["webhooks"],"summary":"List the events created for one endpoint","description":"Filter by delivery state, by event type, and by a window on `created_at`. Every filter is additive to the reference spec and composes with the cursor.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"before","in":"query"},{"schema":{"type":"string","enum":["pending","attempting","success","failed"],"description":"Only events in this delivery state."},"required":false,"description":"Only events in this delivery state.","name":"status","in":"query"},{"schema":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"],"description":"Only events of this type, such as `email.bounced`."},"required":false,"description":"Only events of this type, such as `email.bounced`.","name":"type","in":"query"},{"schema":{"type":"string","description":"ISO 8601 instant, inclusive. Events created before this are excluded."},"required":false,"description":"ISO 8601 instant, inclusive. Events created before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601 instant, inclusive. Must be at or after `start_date`."},"required":false,"description":"ISO 8601 instant, inclusive. Must be at or after `start_date`.","name":"end_date","in":"query"}],"responses":{"200":{"description":"A page of events.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"}},"/api/v1/webhooks/{webhook_id}/parked/deliver":{"post":{"tags":["webhooks"],"summary":"Deliver the events parked while the endpoint was disabled","description":"Replays the oldest parked events in order, at most 10 per call, inside the same per-team budget as a single replay (10 per minute). When the budget runs out delivery stops with `stopped_reason: \"rate_limit_exceeded\"`; `remaining` is how many events are still parked. A disabled endpoint is `422 validation_error`: enable it first.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"}],"responses":{"200":{"description":"What was delivered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParkedDelivery"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"}},"/api/v1/webhooks/{webhook_id}/parked":{"get":{"tags":["webhooks"],"summary":"List the events parked while the endpoint was disabled","description":"An auto-disabled endpoint keeps receiving events without delivering them. Oldest first, because a backlog is delivered in the order it happened. `has_more` is true when more are parked than `limit`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"example":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"The parked events, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParkedWebhookEventList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"}},"/api/v1/webhooks/{webhook_id}":{"get":{"tags":["webhooks"],"summary":"Read one webhook endpoint","description":"`signing_secret` is masked. The plaintext is returned only by create and rotate-secret.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDetail"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:read"},"patch":{"tags":["webhooks"],"summary":"Change the endpoint, its subscriptions or its status","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endpoint":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["email.sent","email.scheduled","email.delivered","email.delivery_delayed","email.bounced","email.complained","email.opened","email.clicked","email.failed","email.suppressed","email.canceled","domain.created","domain.updated","domain.deleted","suppression.added","suppression.removed","contact.created","contact.updated","contact.deleted","email.received","automation.run.started","automation.run.completed","automation.run.failed"]},"minItems":1},"status":{"type":"string","enum":["enabled","disabled"]}},"additionalProperties":false}}}},"responses":{"200":{"description":"The updated endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRef"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"},"delete":{"tags":["webhooks"],"summary":"Delete a webhook endpoint","description":"The row is kept so past events and attempts keep their join; it stops receiving events.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"9f8a3b21-7c4e-4f0a-9f2f-6f6d1c1a0b55"},"required":true,"name":"webhook_id","in":"path"}],"responses":{"200":{"description":"The deleted endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteWebhookResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"webhooks:write"}},"/api/v1/logs":{"get":{"tags":["logs"],"summary":"List API request logs","description":"Every request made with this team's credentials, newest first — including the writes the dashboard made on your behalf, which are logged with `source: dashboard`. Rows are kept for your plan's retention window (30 days by default) and then deleted, so a log older than that is absent rather than empty. Reading this endpoint writes a row of its own.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return logs after this ID."},"required":false,"description":"Return logs after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return logs before this ID."},"required":false,"description":"Return logs before this ID.","name":"before","in":"query"},{"schema":{"type":"integer","minimum":100,"maximum":599,"description":"The response status recorded on the row, such as 422."},"required":false,"description":"The response status recorded on the row, such as 422.","name":"status","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512,"description":"An exact User-Agent, as it was sent."},"required":false,"description":"An exact User-Agent, as it was sent.","name":"user_agent","in":"query"},{"schema":{"type":"string","description":"The client that made the request: `api`, `dashboard`, or `sdk:<name>`."},"required":false,"description":"The client that made the request: `api`, `dashboard`, or `sdk:<name>`.","name":"source","in":"query"},{"schema":{"type":"string","description":"Leave out one source, spelled as `source` is — `dashboard` for every request your code made."},"required":false,"description":"Leave out one source, spelled as `source` is — `dashboard` for every request your code made.","name":"exclude_source","in":"query"},{"schema":{"type":"string","description":"Case-insensitive text in the endpoint (`/emails/{email_id}`) or the requested path, so an ID finds the requests that named it. 1–200 characters after trimming."},"required":false,"description":"Case-insensitive text in the endpoint (`/emails/{email_id}`) or the requested path, so an ID finds the requests that named it. 1–200 characters after trimming.","name":"search","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Logs created before this are excluded."},"required":false,"description":"ISO 8601, inclusive. Logs created before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Logs created after this are excluded."},"required":false,"description":"ISO 8601, inclusive. Logs created after this are excluded.","name":"end_date","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"logs:read"}},"/api/v1/logs/{log_id}":{"get":{"tags":["logs"],"summary":"Retrieve a single API request log","description":"`request_body` is the body as it was stored: a body naming a secret-looking field was dropped whole, and a send's message content was replaced by its measurements before the row was written (07 §8). `response_body` is present for a failed request only. A log belonging to another team is `404`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"0198f4c1-0000-7000-8000-000000000000"},"required":true,"name":"log_id","in":"path"}],"responses":{"200":{"description":"The log.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Log"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"logs:read"}},"/api/v1/templates":{"post":{"tags":["templates"],"summary":"Create a template","description":"Creates the template as a draft holding version 1. Send **either** `html`, or `starter` to start from one of the starter templates -- exactly one of the two. With `starter`, the entry's subject, bodies and variables become version 1, and `subject`, `text` and `variables` sent beside it override them; the copy is an ordinary template from that moment, with no link back to the library. Every `{{key}}` in `subject`, `html` and `text` must be declared in `variables`, and every declared key must be used; an alias must be free among the team's live templates. Nothing is sent from it until it is published.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateRequest"}}}},"responses":{"201":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"},"get":{"tags":["templates"],"summary":"Retrieve a list of templates","description":"Most recently changed first. Items carry no content and no `object`, exactly as the reference document has them; `alias` is present only where one is set. `search` matches the name or alias; `status` filters by status.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Only templates whose name or alias contains this term, case-insensitively. `%` and `_` match themselves."},"required":false,"description":"Only templates whose name or alias contains this term, case-insensitively. `%` and `_` match themselves.","name":"search","in":"query"},{"schema":{"type":"string","enum":["draft","published"],"description":"Only templates in this status."},"required":false,"description":"Only templates in this status.","name":"status","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTemplatesResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"}},"/api/v1/templates/{id}":{"get":{"tags":["templates"],"summary":"Retrieve a single template","description":"The template with its **current** version's content -- the draft, when one is open. `has_unpublished_versions` says whether that differs from what sends use. `alias`, `from`, `subject` and `text` are absent rather than `null` when unset.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"},"patch":{"tags":["templates"],"summary":"Update an existing template","description":"Writes the draft. On a published template with no open draft this starts the next version and leaves sends untouched until `publish`; on an open draft it edits in place. Only the fields present change; `alias`, `from` and `subject` accept `null` to clear them. An empty body is refused.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateOptions"}}}},"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"},"delete":{"tags":["templates"],"summary":"Remove an existing template","description":"Soft-deletes: the template answers 404 from this moment, its alias is free to reuse, and emails already sent from it keep their record of which version they used.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveTemplateResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"}},"/api/v1/templates/{id}/publish":{"post":{"tags":["templates"],"summary":"Publish a template","description":"Makes the current version the one sends resolve to. Publishing a template whose current version is already published changes nothing and still answers 200.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishTemplateResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"}},"/api/v1/templates/{id}/duplicate":{"post":{"tags":["templates"],"summary":"Duplicate a template","description":"Copies the **current** version into a new draft template named `<name> (copy)` with no alias. The source is untouched.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"responses":{"200":{"description":"The new template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateTemplateResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"}},"/api/v1/templates/{id}/preview":{"post":{"tags":["templates"],"summary":"Preview a template with values filled in","description":"Renders the **current** version, or the `version` named, with `variables` substituted the way a send substitutes them: an undeclared key or a value of the wrong type is `422 invalid_parameter`. A declared variable with neither a value nor a fallback is listed in `missing_variables` and its placeholder is left in place. `html` has been through the dashboard preview's sanitizer, with remote images withheld: put it in a sandboxed iframe's `srcdoc`, never straight into a page. Nothing is stored and nothing is sent.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePreviewRequest"}}}},"responses":{"200":{"description":"The rendered version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplatePreview"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"}},"/api/v1/templates/{id}/test":{"post":{"tags":["templates"],"summary":"Send a test of a template","description":"Sends the **current** version (the open draft, when there is one) to one to five addresses with `[Test] ` before the subject. Each is an ordinary email and counts as a send. A variable with no value and no fallback is `422 missing_required_field`; with no `from` on the template or the request, so is the send. The token also needs `emails:send`.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"},{"schema":{"type":"string","maxLength":256,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`."},"required":false,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateTestOptions"}}}},"responses":{"202":{"description":"The emails created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateTest"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"}},"/api/v1/templates/{id}/versions":{"get":{"tags":["templates"],"summary":"List a template's versions","description":"Newest first, without bodies: `current` is the version reads show and edits write, `published` the one sends use. Read an older version's content with `POST /templates/{id}/preview` and its `version`.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The versions, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateVersionList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"}},"/api/v1/templates/{id}/versions/{version_number}/restore":{"post":{"tags":["templates"],"summary":"Restore a template version","description":"Copies that version into a new draft version and makes it current. The version sends use does not change until you publish. Restoring the version that is already current is `409 resource_locked`.","parameters":[{"schema":{"type":"string","description":"The Template ID or alias.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The Template ID or alias.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"description":"The version to restore.","example":1},"required":true,"description":"The version to restore.","name":"version_number","in":"path"}],"responses":{"200":{"description":"The template and its new draft version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoredTemplateVersion"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"templates:write"}},"/api/v1/starters":{"get":{"tags":["templates"],"summary":"List the starter templates","description":"The curated library, in the order the dashboard shows it. Items carry the subject and the declared variables but **no bodies** -- retrieve one starter for its HTML and plain text. The catalogue is the same for every project and is not paginated.","responses":{"200":{"description":"The catalogue.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStartersResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"}},"/api/v1/starters/{slug}":{"get":{"tags":["templates"],"summary":"Retrieve a starter template","description":"One starter in full: its HTML and plain-text bodies, the variables a copy will declare, and sample values to preview it with. The bodies carry `{{brand.*}}` tokens, which resolve from the project's brand kit when a copy is rendered, and `{{key}}` placeholders, which a send fills.","parameters":[{"schema":{"type":"string","description":"The starter template's slug.","example":"receipt"},"required":true,"description":"The starter template's slug.","name":"slug","in":"path"}],"responses":{"200":{"description":"The starter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Starter"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"templates:read"}},"/api/v1/emails/metrics":{"get":{"tags":["emails"],"summary":"Retrieve account-level email metrics","description":"Totals are aggregated in one-minute buckets by the `metrics-rollup` job. `end_date` is clamped to the last completed bucket, which the additive `data_as_of` field names. `sent` counts emails; `delivered`, `bounced` and `complained` count recipients. Rate metrics are fractions between 0 and 1: `delivery_rate`, `bounce_rate` and `complaint_rate` are of the recipients with an outcome (delivered + bounced); `open_rate` and `click_rate` are unique emails opened or clicked of emails sent. Periods are UTC days; `email_id`, `broadcast_id`, the `email` and `broadcast` dimensions and any timezone but UTC are refused with `422 invalid_parameter`.","parameters":[{"schema":{"type":"string","description":"ISO 8601 date or datetime. Defaults to 6 days before end_date."},"required":false,"description":"ISO 8601 date or datetime. Defaults to 6 days before end_date.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601 date or datetime. Clamped to the last completed bucket."},"required":false,"description":"ISO 8601 date or datetime. Clamped to the last completed bucket.","name":"end_date","in":"query"},{"schema":{"type":"string","description":"Only `UTC` is supported: periods are UTC days. Any other zone is refused."},"required":false,"description":"Only `UTC` is supported: periods are UTC days. Any other zone is refused.","name":"timezone","in":"query"},{"schema":{"type":"string","enum":["hourly","daily","weekly","monthly"],"description":"Bucket size when period is a dimension."},"required":false,"description":"Bucket size when period is a dimension.","name":"granularity","in":"query"},{"schema":{"type":"string","description":"Comma-separated. One or more of: received, delivered, complained, suppressed, bounced, bounced_transient, bounced_permanent, bounced_undetermined, opened, clicked, delivery_delayed, failed, sent, unique_opened, unique_clicked, delivery_rate, open_rate, click_rate, bounce_rate, complaint_rate, attempted."},"required":false,"description":"Comma-separated. One or more of: received, delivered, complained, suppressed, bounced, bounced_transient, bounced_permanent, bounced_undetermined, opened, clicked, delivery_delayed, failed, sent, unique_opened, unique_clicked, delivery_rate, open_rate, click_rate, bounce_rate, complaint_rate, attempted.","name":"metrics","in":"query"},{"schema":{"type":"string","description":"Comma-separated. One or more of: period, domain, email, broadcast. Only period and domain are available; email and broadcast are refused."},"required":false,"description":"Comma-separated. One or more of: period, domain, email, broadcast. Only period and domain are available; email and broadcast are refused.","name":"dimensions","in":"query"},{"schema":{"type":"string","description":"Comma-separated UUIDs."},"required":false,"description":"Comma-separated UUIDs.","name":"domain_id","in":"query"},{"schema":{"type":"string","description":"Not supported: metrics are aggregated per team and domain. Refused when present."},"required":false,"description":"Not supported: metrics are aggregated per team and domain. Refused when present.","name":"email_id","in":"query"},{"schema":{"type":"string","description":"Not supported: metrics are aggregated per team and domain. Refused when present; a broadcast's own numbers are its recipients."},"required":false,"description":"Not supported: metrics are aggregated per team and domain. Refused when present; a broadcast's own numbers are its recipients.","name":"broadcast_id","in":"query"}],"responses":{"200":{"description":"The metrics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetEmailsMetricsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/receiving/{email_id}/raw/download":{"get":{"tags":["receiving"],"summary":"Download the raw message through a signed link","description":"The message exactly as it reached us, as `raw.eml`. Authenticated by the link's own signature rather than by an API key, so a browser can follow it; valid for 15 minutes and for this message only.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","description":"Milliseconds since the epoch; part of the signed claim."},"required":true,"description":"Milliseconds since the epoch; part of the signed claim.","name":"expires","in":"query"},{"schema":{"type":"string","description":"The link's signature."},"required":true,"description":"The link's signature.","name":"token","in":"query"}],"responses":{"200":{"description":"The bytes, as an attachment.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"The link is invalid, has expired, or names nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/emails/receiving/{email_id}/attachments/{attachment_id}/download":{"get":{"tags":["receiving"],"summary":"Download a received attachment through a signed link","description":"The target of `download_url`. Authenticated by the link's own signature rather than by an API key, so a browser can follow it; valid for 15 minutes and for this attachment only.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"660e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"attachment_id","in":"path"},{"schema":{"type":"string","description":"Milliseconds since the epoch; part of the signed claim."},"required":true,"description":"Milliseconds since the epoch; part of the signed claim.","name":"expires","in":"query"},{"schema":{"type":"string","description":"The link's signature."},"required":true,"description":"The link's signature.","name":"token","in":"query"}],"responses":{"200":{"description":"The bytes, as an attachment.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"The link is invalid, has expired, or names nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/emails/receiving":{"get":{"tags":["receiving"],"summary":"List received emails","description":"Newest first. Cursors are received-email IDs. A message we recorded but would not store carries a `dropped_reason` and no attachments. `search`, `start_date` and `end_date` narrow the list.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive substring of the subject, the sender's address or name, or any recipient. `%` and `_` match literally."},"required":false,"description":"Case-insensitive substring of the subject, the sender's address or name, or any recipient. `%` and `_` match literally.","name":"search","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Messages received before this are excluded."},"required":false,"description":"ISO 8601, inclusive. Messages received before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Messages received after this are excluded."},"required":false,"description":"ISO 8601, inclusive. Messages received after this are excluded.","name":"end_date","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListReceivedEmailsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/receiving/{email_id}":{"get":{"tags":["receiving"],"summary":"Retrieve a received email","description":"The message with its headers, bodies and attachment list. The raw source is not included; `…/raw/download` serves it. The bodies are read from the stored message when it is opened: if that read fails the response is `503 service_unavailable` and the message is still there — retry, rather than treating the id as gone.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"The message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetReceivedEmailResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The message's stored source could not be read right now; the message still exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"},"delete":{"tags":["receiving"],"summary":"Delete a received email","description":"Removes the stored objects and the record, and returns the storage to this team's inbound quota. There is no undo, and no soft delete: the message is gone.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteReceivedEmailResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/emails/receiving/{email_id}/attachments":{"get":{"tags":["receiving"],"summary":"List the attachments of a received email","description":"Cursors are attachment IDs; the page is in the order the parts appeared in the message. A stored part carries a signed `download_url`; one we refused to store is listed with its size and no link.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAttachmentsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/receiving/{email_id}/attachments/{attachment_id}":{"get":{"tags":["receiving"],"summary":"Retrieve one attachment of a received email","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"660e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"attachment_id","in":"path"}],"responses":{"200":{"description":"The attachment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedAttachment"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/share":{"post":{"tags":["emails"],"summary":"Create a shareable link for a sent email","description":"Returns a link that opens a read-only view of this email on a separate origin, with no sign-in. `expires_in` is a duration such as `10m`, `2 hours` or `1 day`; it defaults to 48 hours and may not exceed them. The link is shown once and cannot be retrieved again.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareEmailOptions"}}}},"responses":{"200":{"description":"The link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareEmailResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/shares/{share_id}":{"delete":{"tags":["emails"],"summary":"Revoke a shareable link","description":"Stops the link working on the next request. Idempotent: revoking a link that is already revoked answers the instant it *first* stopped working rather than the instant of this call, and the row is kept either way — a link that was shared and withdrawn is a fact about this email. A share belonging to another email, or to another team, is `404`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"0198f4c1-0000-7000-8000-000000000000"},"required":true,"name":"share_id","in":"path"}],"responses":{"200":{"description":"The withdrawn link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteEmailShareResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/shares":{"get":{"tags":["emails"],"summary":"List the shareable links of a sent email","description":"Every link ever minted for this email, newest first, live and withdrawn alike. **No link is returned**: only a hash of each token is stored, so neither the URL nor any part of it can be recovered — a lost link is revoked and replaced, never re-shown. Cursors are share IDs.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailShareList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/attachments/{attachment_id}/download":{"get":{"tags":["emails"],"summary":"Download an attachment through a signed link","description":"The target of `download_url`. Authenticated by the link's own signature rather than by an API key, so a browser can follow it; valid for 15 minutes and for this attachment only.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"660e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"attachment_id","in":"path"},{"schema":{"type":"string","description":"Milliseconds since the epoch; part of the signed claim."},"required":true,"description":"Milliseconds since the epoch; part of the signed claim.","name":"expires","in":"query"},{"schema":{"type":"string","description":"The link's signature."},"required":true,"description":"The link's signature.","name":"token","in":"query"}],"responses":{"200":{"description":"The attachment bytes.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"The link is invalid, has expired, or names nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/emails/{email_id}/attachments/{attachment_id}":{"get":{"tags":["emails"],"summary":"Retrieve one attachment of a sent email","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"660e8400-e29b-41d4-a716-446655440000"},"required":true,"name":"attachment_id","in":"path"}],"responses":{"200":{"description":"The attachment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetrievedAttachment"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/attachments":{"get":{"tags":["emails"],"summary":"List the attachments of a sent email","description":"Cursors are attachment IDs. Each item carries a signed `download_url`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/batch":{"post":{"tags":["emails"],"summary":"Send up to 100 emails in one request","description":"All-or-nothing validation: one invalid element rejects the whole batch, naming its index as `emails[3]`, and nothing is stored. All elements are written in one transaction and the ids come back in input order.","parameters":[{"schema":{"type":"string","maxLength":256,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`."},"required":false,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBatchEmailsRequest"}}}},"responses":{"200":{"description":"The accepted emails, in input order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBatchEmailsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The Idempotency-Key was replayed with a different payload, or is in flight.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The request body is larger than the configured limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Sending is paused, or a dependency is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"emails:send"}},"/api/v1/emails":{"post":{"tags":["emails"],"summary":"Send an email","description":"Returns as soon as the email is committed; delivery happens in the background. `scheduled_at` takes an ISO 8601 instant or a phrase such as `in 2 hours` or `tomorrow at 9am`, read as UTC.","parameters":[{"schema":{"type":"string","maxLength":256,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`."},"required":false,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequest"}}}},"responses":{"200":{"description":"The accepted email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The Idempotency-Key was replayed with a different payload, or is in flight.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The request body is larger than the configured limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Sending is paused, or a dependency is unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"emails:send"},"get":{"tags":["emails"],"summary":"List emails, newest first","description":"Every filter is optional and additive: sending none returns the same page it always did. They are applied in the query rather than to the page, so `has_more` describes the list you asked for.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","enum":["queued","scheduled","sent","delivered","delivery_delayed","bounced","complained","opened","clicked","failed","suppressed","canceled"],"description":"The last event the email reached, such as `delivered` or `bounced`."},"required":false,"description":"The last event the email reached, such as `delivered` or `bounced`.","name":"status","in":"query"},{"schema":{"type":"string","description":"Only emails sent with this API key. A revoked key still filters what it sent."},"required":false,"description":"Only emails sent with this API key. A revoked key still filters what it sent.","name":"api_key_id","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Emails created before this are excluded."},"required":false,"description":"ISO 8601, inclusive. Emails created before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Emails created after this are excluded."},"required":false,"description":"ISO 8601, inclusive. Emails created after this are excluded.","name":"end_date","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive substring of the subject, the sender address or any recipient address. `%` and `_` match literally."},"required":false,"description":"Case-insensitive substring of the subject, the sender address or any recipient address. `%` and `_` match literally.","name":"search","in":"query"},{"schema":{"type":"string","description":"Comma-separated, each `name:value`. Up to 10; an email has to carry all of them. Repeating the parameter, as `tags` or `tags[]`, does the same."},"required":false,"description":"Comma-separated, each `name:value`. Up to 10; an email has to carry all of them. Repeating the parameter, as `tags` or `tags[]`, does the same.","name":"tags","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}":{"get":{"tags":["emails"],"summary":"Retrieve a single email","description":"`html` and `text` are null once retention has removed the bodies; `last_event` still describes what happened.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"The email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Email"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"},"patch":{"tags":["emails"],"summary":"Reschedule a scheduled email","description":"Allowed only while the email is still scheduled and its job unclaimed. An email already sent, failed or canceled is `400 validation_error`; a job being claimed right now is `409 resource_locked`, which may be retried.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailOptions"}}}},"responses":{"200":{"description":"The rescheduled email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRef"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The send has already started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/emails/{email_id}/cancel":{"post":{"tags":["emails"],"summary":"Cancel a scheduled email","description":"Refunds the quota it was charged at acceptance and records a compensating usage event. The sleeping workflow run is left alone: it wakes, sees the canceled job and exits.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"The canceled email.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRef"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The send has already started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/contact-properties":{"post":{"tags":["contact-properties"],"summary":"Create a new contact property","description":"`key` is unique within the team; a duplicate is `422 invalid_parameter`. `fallback_value` must match `type`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactPropertyOptions"}}}},"responses":{"201":{"description":"The property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactPropertyResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"},"get":{"tags":["contact-properties"],"summary":"Retrieve a list of contact properties","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContactPropertiesResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"}},"/api/v1/contact-properties/{contact_property_id}":{"get":{"tags":["contact-properties"],"summary":"Retrieve a single contact property","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Contact Property ID.","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"},"required":true,"description":"The Contact Property ID.","name":"contact_property_id","in":"path"}],"responses":{"200":{"description":"The property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetContactPropertyResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"},"patch":{"tags":["contact-properties"],"summary":"Update an existing contact property","description":"`fallback_value` only; `key` and `type` are immutable. `null` clears it.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Contact Property ID.","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"},"required":true,"description":"The Contact Property ID.","name":"contact_property_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactPropertyOptions"}}}},"responses":{"200":{"description":"The property.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactPropertyResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"},"delete":{"tags":["contact-properties"],"summary":"Remove an existing contact property","description":"Removes the declaration and the key from every contact that carried a value for it.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Contact Property ID.","example":"b6d24b8e-af0b-4c3c-be0c-359bbd97381e"},"required":true,"description":"The Contact Property ID.","name":"contact_property_id","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveContactPropertyResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"}},"/api/v1/contacts/imports":{"post":{"tags":["contacts"],"summary":"Create a contact import","description":"Uploads a CSV of up to 50 MB as `multipart/form-data` and starts an import. The response arrives as soon as the file is stored; the import itself runs in the background, and reading the import back reports its status and counts. `column_map`, `segments` and `topics` are JSON-encoded strings. Rows past the plan's contact limit are counted as failed with `contact_limit_reached`. No `contact.*` webhook is emitted per row.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CreateContactImportOptions"}}}},"responses":{"201":{"description":"The import, queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactImportResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The file is over 50 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"No file store is configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"},"get":{"tags":["contacts"],"summary":"Retrieve a list of contact imports","description":"Newest first. `status` narrows the page to one status.","parameters":[{"schema":{"type":"string","enum":["queued","in_progress","completed","failed"],"description":"Filter contact imports by status."},"required":false,"description":"Filter contact imports by status.","name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContactImportsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"}},"/api/v1/contacts/imports/{id}":{"get":{"tags":["contacts"],"summary":"Retrieve a single contact import","description":"The import's status and counts. `completed_at` is set once the import has finished, whether it completed or failed.","parameters":[{"schema":{"type":"string","description":"The Contact Import ID.","example":"479e3145-dd38-476b-932c-529ceb705947"},"required":true,"description":"The Contact Import ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The import.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"}},"/api/v1/contacts":{"post":{"tags":["contacts"],"summary":"Create a new contact","description":"An address the team already holds a contact for is updated with the fields the body carries and its existing id is returned; a repeat create never resubscribes an opted-out contact. Every key in `properties` must be a declared contact property of a matching type. `plans.marketing_contacts_included` is enforced here with `422 validation_error`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactOptions"}}}},"responses":{"201":{"description":"The contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"},"get":{"tags":["contacts"],"summary":"Retrieve a list of contacts","description":"Newest first. Items carry no `properties`, and the envelope carries no `has_more`, exactly as the reference document has it; walk pages with `after`.","parameters":[{"schema":{"type":"string","description":"Filter by segment ID."},"required":false,"description":"Filter by segment ID.","name":"segment_id","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContactsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"}},"/api/v1/contacts/{contact}":{"get":{"tags":["contacts"],"summary":"Retrieve a single contact by ID or email","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"}],"responses":{"200":{"description":"The contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetContactResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"contacts:read"},"patch":{"tags":["contacts"],"summary":"Update a single contact by ID or email","description":"Only the fields present are changed. `properties` merges key by key; a `null` value removes the key. Setting `unsubscribed` is the contact's global subscription state.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactOptions"}}}},"responses":{"200":{"description":"The contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"},"delete":{"tags":["contacts"],"summary":"Remove an existing contact by ID or email","description":"Erasure, not a soft delete: the contact's personal data is removed and the contact is a 404 from that moment. Consent records are kept with an email hash only.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveContactResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"contacts:write"}},"/api/v1/segments":{"post":{"tags":["segments"],"summary":"Create a new segment","description":"`filter` is validated against the team's contact properties when the segment is created: an undeclared property or an operator that does not suit its type is `422 validation_error` with one `errors[]` entry per condition. A segment without a filter has explicit membership only. The filter cannot be changed later.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSegmentOptions"}}}},"responses":{"201":{"description":"The segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"segments:write"},"get":{"tags":["segments"],"summary":"Retrieve a list of segments","description":"Newest first. Items carry no `filter`; read one segment for its filter.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSegmentsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"}},"/api/v1/segments/preview":{"post":{"tags":["segments"],"summary":"Count the contacts a filter matches","description":"How many contacts `filter` matches right now, for a segment that does not exist yet. Nothing is stored. The filter is checked exactly as `POST /segments` checks it, so a filter that would be refused there is `422 validation_error` here with the same `errors[]` paths.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentPreviewRequest"}}}},"responses":{"200":{"description":"The count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentPreview"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"}},"/api/v1/segments/{segment}/contacts":{"get":{"tags":["segments"],"summary":"Retrieve the contacts in a segment","description":"The segment's members: the contacts its filter matches together with those added explicitly, minus deleted contacts, evaluated now. Newest first, paged like `/contacts`. This is the audience a broadcast to the segment would resolve.","parameters":[{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentContactList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"}},"/api/v1/segments/{segment}/metrics":{"get":{"tags":["segments"],"summary":"Retrieve the size of a segment","description":"How many contacts the segment resolves to right now, and how they split on the global unsubscribe. One pass over the same membership `/contacts` lists.","parameters":[{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"responses":{"200":{"description":"The counts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SegmentMetrics"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"}},"/api/v1/segments/{segment}":{"get":{"tags":["segments"],"summary":"Retrieve a single segment","parameters":[{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"responses":{"200":{"description":"The segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"},"patch":{"tags":["segments"],"summary":"Update an existing segment","description":"Renames the segment. A filter cannot be changed: a `filter` in the body is `422 invalid_parameter`; create a new segment instead.","parameters":[{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSegmentOptions"}}}},"responses":{"200":{"description":"The segment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"segments:write"},"delete":{"tags":["segments"],"summary":"Remove an existing segment","description":"Soft-deletes the segment and frees its name; it is a 404 from that moment. Explicit memberships are kept with the row so a past broadcast's report can still name its audience.","parameters":[{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"segments:write"}},"/api/v1/contacts/{contact}/segments":{"get":{"tags":["contacts"],"summary":"Retrieve a list of segments for a contact","description":"Every segment the contact is in right now: those it was added to explicitly and those whose filter it matches. Newest segment first.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListContactSegmentsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"segments:read"}},"/api/v1/contacts/{contact}/segments/{segment}":{"post":{"tags":["contacts"],"summary":"Add a contact to a segment","description":"Explicit membership. Adding a contact that is already a member changes nothing.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"},{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"responses":{"200":{"description":"The membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContactToSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"segments:write"},"delete":{"tags":["contacts"],"summary":"Remove a contact from a segment","description":"Removes an explicit membership. A contact the segment's filter matches stays a member: a filter is a rule, not a list.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact","in":"path"},{"schema":{"type":"string","description":"The Segment ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Segment ID.","name":"segment","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveContactFromSegmentResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"segments:write"}},"/api/v1/billing/payg":{"post":{"tags":["billing"],"summary":"Switch \"Continue using the service beyond your quota.\" on or off","description":"Sets `pay_as_you_go_enabled` for the caller's team. It is on by default once the team is on a paid plan with a payment method on file; setting it here makes it the team's own choice, and it is not switched automatically again. Switching it on requires a plan with an overage rate (never `free`) and a payment method on file, else `422 validation_error` naming what is missing. There is no overage ceiling: `overage_ceiling_emails` stays null unless one was set for the team, and the project's spend cap still applies. Pay-as-you-go raises only the plan's monthly component, never the daily cap, the sending-tier cap or a restricted team's limits. Every toggle writes a `billing.payg_toggled` audit row. Toggle copy: \"Continue using the service beyond your quota.\"","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPaygRequest"}}}},"responses":{"200":{"description":"The toggle's state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingPaygResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/spend-cap":{"get":{"tags":["billing"],"summary":"Read the project's monthly spend cap","description":"Every project has a monthly cap on how much it may send, counted in billable recipients across both meters. Reaching it pauses that project's sending and leaves every other project on the account untouched; the pause lifts when the cap is raised above the usage, and when the next month begins. A project that has set no cap of its own is held to ten times its monthly allowance, which is what `is_default` reports. `used_emails` is what this project has sent in the current month, which is the number the cap is compared against.","responses":{"200":{"description":"The cap, the ladder and the usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSpendCapResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null},"post":{"tags":["billing"],"summary":"Set the project's monthly spend cap","description":"Every project has a monthly cap on how much it may send, counted in billable recipients across both meters. Reaching it pauses that project's sending and leaves every other project on the account untouched; the pause lifts when the cap is raised above the usage, and when the next month begins. A project that has set no cap of its own is held to ten times its monthly allowance, which is what `is_default` reports. Saving takes effect at once in both directions: a cap above the month's usage lifts a pause the cap itself caused, and a cap at or below it pauses the project there and then. A pause an operator set for another reason is never lifted here. Every save writes a `billing.spend_cap_changed` audit row.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSpendCapRequest"}}}},"responses":{"200":{"description":"The cap as it now stands.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSpendCapResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/addons":{"post":{"tags":["billing"],"summary":"Buy an add-on, or set how many units of one the team holds","description":"A team admin's session or a `full_access` API key (A110). `extra_domains_100` ($20 per 100 domains) raises the team's domain limit by 100 per unit and takes effect at once. `dedicated_ip` ($30) is provisioned as you buy it: a dedicated sending address is moved into a pool of your own and attached to your sending, and the add-on reaches `active` within the request. Its `status` is `provisioning` for the moment that takes, and stays there if we have no address free — we are told, and it is finished for you. Warm-up then runs on its own, and `GET /billing` shows how far along it is. There is no volume requirement; we recommend one from about 5,000 emails a day and report your own average beside it. `sso` ($150) is allowed on `scale`, any `scale_*` rung and `enterprise`, and is `422 validation_error` below that; on `enterprise` it is included, so the add-on is recorded `active` with no Stripe item and nothing is charged through the subscription. Removing `sso`, or dropping below Scale, disables the team's SSO connection and clears its enforcement first, so nobody is locked out. A marketing plan sets how many contacts the team may hold and how much marketing mail it may send a month, both reported by `GET /billing`; the seven are mutually exclusive, so buying one while another is held moves the team to it and cancels the old line in the same call, and each takes `quantity` 1. `inbox_storage_100gb` ($15) adds 100 GB of room to the team's Inbox on top of what the plan includes, and takes `quantity` 1. Every add-on is an item on the team's Stripe subscription, so a team without an active one is refused with `422 validation_error` carrying `details.next: \"checkout\"` — start a subscription with `POST /billing/checkout`, which for `inbox_storage_100gb` can buy the add-on on its own. Everything except `inbox_storage_100gb` additionally needs a paid plan, so a team that bought inbox storage on its own is still refused the rest of the catalogue. `quantity` is a set, not an increment.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseAddonRequest"}}}},"responses":{"200":{"description":"What the team now holds of this add-on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamAddon"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The add-on changed while the request was in flight; retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"This plan or add-on is not available for purchase yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/billing/addons/{addon_code}":{"delete":{"tags":["billing"],"summary":"Remove an add-on","description":"A team admin's session or a `full_access` API key. Removing `sso` off Enterprise turns single sign-on off, so an API key is refused it with 403 and a signed-in admin removes it. The subscription item is removed with a proration and the add-on's `status` becomes `canceled`. Removing `extra_domains_100` leaves every existing domain in place: nothing is deleted, and the next domain create is refused by the lower limit. Removing a marketing plan behaves the same way: the contacts the team already holds stay, and the next create is refused by the plan's own limit. Removing a `dedicated_ip` still open with the operator withdraws the request.","parameters":[{"schema":{"type":"string","enum":["extra_domains_100","dedicated_ip","sso","marketing_5k","marketing_10k","marketing_15k","marketing_25k","marketing_50k","marketing_100k","marketing_150k","inbox_storage_100gb","inbox_seat"],"example":"extra_domains_100"},"required":true,"name":"addon_code","in":"path"}],"responses":{"200":{"description":"The add-on, now canceled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamAddon"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/contacts/{contact_id}/topics":{"get":{"tags":["contacts"],"summary":"Retrieve topics for a contact","description":"Every live topic of the team with the contact's effective subscription: the contact's own choice where one was recorded, the topic's `default_subscription` otherwise.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact_id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetContactTopicsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"topics:read"},"patch":{"tags":["contacts"],"summary":"Update topics for a contact","description":"Records an explicit choice per topic named, and one consent record per change. A topic id that is not a live topic of the team is `422 invalid_parameter`.","parameters":[{"schema":{"type":"string","description":"The Contact ID or email address.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Contact ID or email address.","name":"contact_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactTopicsOptions"}}}},"responses":{"200":{"description":"The subscriptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactTopicsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"topics:write"}},"/api/v1/topics":{"post":{"tags":["topics"],"summary":"Create a new topic","description":"`default_subscription` is what a contact with no explicit choice is treated as, and cannot be changed after creation. `visibility` defaults to `private`. A live topic already named `name` is `422 invalid_parameter`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTopicOptions"}}}},"responses":{"201":{"description":"The topic.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTopicResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"topics:write"},"get":{"tags":["topics"],"summary":"Retrieve a list of topics","description":"Newest first; walk pages with `after`.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTopicsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"topics:read"}},"/api/v1/topics/{id}":{"get":{"tags":["topics"],"summary":"Retrieve a single topic","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Topic ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Topic ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The topic.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTopicResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"topics:read"},"patch":{"tags":["topics"],"summary":"Update an existing topic","description":"Only `name`, `description` and `visibility` change; a body carrying `default_subscription` is refused with `422 invalid_parameter`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Topic ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Topic ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTopicOptions"}}}},"responses":{"200":{"description":"The topic.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTopicResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"topics:write"},"delete":{"tags":["topics"],"summary":"Remove an existing topic","description":"A soft delete: the topic is a 404 from that moment and its name is free again, while emails and consent records that name it keep doing so.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The Topic ID.","example":"78261eea-8f8b-4381-83c6-79fa7120f1cf"},"required":true,"description":"The Topic ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveTopicResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"topics:write"}},"/api/v1/broadcasts":{"post":{"tags":["broadcasts"],"summary":"Create a broadcast","description":"Creates a draft. With `send: true` the broadcast goes straight through the compliance gate and is queued (or, with `scheduled_at` — an ISO 8601 instant or a phrase such as `in 2 hours`, read as UTC — scheduled); a gate refusal creates nothing. Bodies may carry `{{{KEY|default}}}` merge variables, rendered per recipient at send time.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBroadcastOptions"}}}},"responses":{"201":{"description":"The broadcast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"},"get":{"tags":["broadcasts"],"summary":"Retrieve a list of broadcasts","description":"Newest first. Deleted drafts are not listed. `search` matches the name or subject; `status` filters by status.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Only broadcasts whose name or subject contains this term, case-insensitively. `%` and `_` match themselves."},"required":false,"description":"Only broadcasts whose name or subject contains this term, case-insensitively. `%` and `_` match themselves.","name":"search","in":"query"},{"schema":{"type":"string","enum":["draft","scheduled","queued","sending","sent","canceled","failed"],"description":"Only broadcasts in this status."},"required":false,"description":"Only broadcasts in this status.","name":"status","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBroadcastsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"broadcasts:read"}},"/api/v1/broadcasts/{id}/send":{"post":{"tags":["broadcasts"],"summary":"Send or schedule a broadcast","description":"Moves a draft to `queued`, or to `scheduled` when `scheduled_at` is given — an ISO 8601 instant or a phrase such as `in 2 hours`, resolved in UTC, at least one minute and at most thirty days out. The compliance gate refuses without a domain with `sending_verified_at`, a postal address on the team, a segment that resolves, the marketing kill switch on, and a team that is neither restricted nor suspended.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBroadcastOptions"}}}},"responses":{"200":{"description":"The broadcast id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"}},"/api/v1/broadcasts/{id}/cancel":{"post":{"tags":["broadcasts"],"summary":"Cancel a broadcast","description":"Cancels a broadcast that is queued or scheduled. Canceling a queued broadcast stops it mid-send; emails already sent are not affected, but no further emails will go out.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The broadcast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"}},"/api/v1/broadcasts/{id}/recipients":{"get":{"tags":["broadcasts"],"summary":"Retrieve broadcast recipients","description":"Retrieve the recipients of a broadcast for a given event type, such as who opened, clicked, or bounced. `type` is required; `bounce_type` is only valid when `type` is `bounced`.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"},{"schema":{"type":"string","enum":["sent","delivered","opened","clicked","bounced","complained","unsubscribed","suppressed"],"description":"The recipient event type to filter by."},"required":true,"description":"The recipient event type to filter by.","name":"type","in":"query"},{"schema":{"type":"string","description":"Filter recipients whose email address contains this value."},"required":false,"description":"Filter recipients whose email address contains this value.","name":"email","in":"query"},{"schema":{"type":"string","enum":["permanent","transient","undetermined"],"description":"Filter bounced recipients by bounce type. Only valid when `type` is `bounced`."},"required":false,"description":"Filter bounced recipients by bounce type. Only valid when `type` is `bounced`.","name":"bounce_type","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBroadcastRecipientsResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"broadcasts:read"}},"/api/v1/broadcasts/{id}/clicked-links":{"get":{"tags":["broadcasts"],"summary":"Retrieve a broadcast's clicked links","description":"Every URL clicked in the broadcast's emails, with total and unique clicks.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBroadcastClickedLinksResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"broadcasts:read"}},"/api/v1/broadcasts/{id}/checklist":{"get":{"tags":["broadcasts"],"summary":"Check what would stop a broadcast from sending","description":"Every condition of the send gate, passed or not, in the order a send checks them. A failed condition carries the error `name` and `message` the send would answer with. Advisory in time only: the send runs the same gate again when it is called.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The checklist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastCompliance"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"broadcasts:read"}},"/api/v1/broadcasts/{id}/duplicate":{"post":{"tags":["broadcasts"],"summary":"Duplicate a broadcast","description":"Copies a broadcast of any status into a new `draft` named `<name> (copy)`. The segment must still exist (`422 invalid_parameter`).","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"responses":{"201":{"description":"The new draft.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"}},"/api/v1/broadcasts/{id}/test":{"post":{"tags":["broadcasts"],"summary":"Send a test of a broadcast","description":"Sends the draft to one to five addresses with `[Test] ` before the subject. Each is an ordinary email and counts as a send. Draft only (`409 resource_locked`); the token also needs `emails:send`.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"},{"schema":{"type":"string","maxLength":256,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`."},"required":false,"description":"Makes the send exactly-once for 24 hours. A replay returns the original response with `Idempotent-Replayed: true`; the same key with a different payload is `409 invalid_idempotent_request`.","name":"Idempotency-Key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastTestOptions"}}}},"responses":{"202":{"description":"The emails created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastTest"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"}},"/api/v1/broadcasts/{id}":{"get":{"tags":["broadcasts"],"summary":"Retrieve a single broadcast","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The broadcast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"broadcasts:read"},"patch":{"tags":["broadcasts"],"summary":"Update an existing broadcast","description":"Draft only: a broadcast past `draft` answers `400 validation_error`.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBroadcastOptions"}}}},"responses":{"200":{"description":"The broadcast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"},"delete":{"tags":["broadcasts"],"summary":"Remove an existing broadcast that is in the draft status","description":"Draft only, as the spec requires; the broadcast is a 404 from that moment.","parameters":[{"schema":{"type":"string","description":"The Broadcast ID.","example":"e169aa45-1ecf-4183-9955-b1499d5701d3"},"required":true,"description":"The Broadcast ID.","name":"id","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveBroadcastResponseSuccess"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"broadcasts:write"}},"/api/v1/oauth/authorize":{"get":{"tags":["oauth"],"summary":"Start an authorization code flow with PKCE","description":"Validates the request and redirects the browser to the consent page. An unknown or disabled client, or a `redirect_uri` the client did not register, renders an error page and never redirects (RFC 6749 §4.1.2.1); every other failure redirects to the client with `error`, `error_description` and `state`.","parameters":[{"name":"response_type","in":"query","required":true,"description":"Always `code`.","schema":{"type":"string"}},{"name":"client_id","in":"query","required":true,"description":"The client's `rkoc_` identifier, or the https URL of its Client ID Metadata Document.","schema":{"type":"string"}},{"name":"redirect_uri","in":"query","required":true,"description":"Exactly one of the client's registered redirect URIs.","schema":{"type":"string"}},{"name":"scope","in":"query","required":false,"description":"Space-separated scopes; the client's registered default when omitted.","schema":{"type":"string"}},{"name":"state","in":"query","required":false,"description":"Returned unchanged with the code or the error; at most 512 characters. Optional.","schema":{"type":"string"}},{"name":"code_challenge","in":"query","required":true,"description":"`BASE64URL(SHA256(code_verifier))`, 43 characters.","schema":{"type":"string"}},{"name":"code_challenge_method","in":"query","required":true,"description":"Always `S256`; `plain` is refused.","schema":{"type":"string"}},{"name":"resource","in":"query","required":false,"description":"RFC 8707 resource indicator; must name this API.","schema":{"type":"string"}}],"responses":{"302":{"description":"To the consent page, or back to the client with an error.","headers":{"location":{"schema":{"type":"string"}}}},"400":{"description":"Unknown client or unregistered redirect URI.","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests from this address.","content":{"text/html":{"schema":{"type":"string"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/oauth/token":{"post":{"tags":["oauth"],"summary":"Exchange an authorization code, or rotate a refresh token","description":"Public clients only. `authorization_code` requires the code, the same `redirect_uri`, the same `client_id` and the PKCE `code_verifier`. `refresh_token` rotates: the presented token is revoked and a new pair issued. A code or refresh token presented twice revokes the whole grant. Errors use RFC 6749 §5.2's shape, not the Rasket error body.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["grant_type","client_id"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string","description":"The `rkoc_` identifier, or the Client ID Metadata Document URL."},"code":{"type":"string","description":"`authorization_code` only."},"redirect_uri":{"type":"string","description":"`authorization_code` only."},"code_verifier":{"type":"string","description":"`authorization_code` only."},"refresh_token":{"type":"string","description":"`refresh_token` only."},"scope":{"type":"string","description":"`refresh_token` only; may narrow, never widen."}}}},"application/json":{"schema":{"type":"object","required":["grant_type","client_id"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"client_id":{"type":"string","description":"The `rkoc_` identifier, or the Client ID Metadata Document URL."},"code":{"type":"string","description":"`authorization_code` only."},"redirect_uri":{"type":"string","description":"`authorization_code` only."},"code_verifier":{"type":"string","description":"`authorization_code` only."},"refresh_token":{"type":"string","description":"`refresh_token` only."},"scope":{"type":"string","description":"`refresh_token` only; may narrow, never widen."}}}}}},"responses":{"200":{"description":"The token pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}}},"400":{"description":"The request or the grant was refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"`invalid_client`: unknown or disabled client.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/automations":{"post":{"tags":["automations"],"summary":"Create an automation","description":"Writes the automation and version 1 of its graph in one transaction. Exactly one step must be a `trigger`, every other step must be reachable from it, the graph must be acyclic, and every template, segment, topic, contact property and custom event it names must exist in this team. `status` defaults to `disabled`, so nothing enrols until you enable it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAutomationRequest"}}}},"responses":{"201":{"description":"The automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAutomationResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"automations:write"},"get":{"tags":["automations"],"summary":"Retrieve a list of automations","description":"Newest first. Items carry no graph and no `object`, exactly as the reference document has them; retrieve one automation for its steps and connections.","parameters":[{"schema":{"type":"string","enum":["enabled","disabled"],"description":"Filter automations by status."},"required":false,"description":"Filter automations by status.","name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive substring of the automations' names. `%` and `_` match literally."},"required":false,"description":"Case-insensitive substring of the automations' names. `%` and `_` match literally.","name":"search","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAutomationsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"automations:read"}},"/api/v1/automations/{automation_id}":{"get":{"tags":["automations"],"summary":"Retrieve a single automation","description":"The automation with its **active** version's `steps` and `connections` -- the version new enrolments will run. A run already in flight keeps the version it started on.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"responses":{"200":{"description":"The automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Automation"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"automations:read"},"patch":{"tags":["automations"],"summary":"Update an automation","description":"A `PATCH` carrying `steps` and `connections` is the publish: it validates the graph, writes the next immutable version and re-points the automation at it, leaving runs in flight on the version they pinned. The two must be sent together. A `PATCH` with only `name` and/or `status` creates no version. `status: \"disabled\"` stops new enrolments and does **not** cancel live runs -- that is `stop`. An empty body is refused.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAutomationRequest"}}}},"responses":{"200":{"description":"The automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAutomationResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"automations:write"},"delete":{"tags":["automations"],"summary":"Delete an automation","description":"Cancels every run still `running`, then soft-deletes: the automation answers 404 from this moment, and each cancelled run raises `automation.run.failed` with the reason `cancelled`.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAutomationResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"automations:write"}},"/api/v1/automations/{automation_id}/duplicate":{"post":{"tags":["automations"],"summary":"Duplicate an automation","description":"Copies the **active** version verbatim into a new `disabled` automation named `<name> (copy)`, at version 1. The copy is not re-validated: what it copies was valid when it was written, and a re-parse would refuse a `delay` whose `until` has since moved closer.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"responses":{"201":{"description":"The new automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateAutomationResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"automations:write"}},"/api/v1/automations/{automation_id}/stop":{"post":{"tags":["automations"],"summary":"Stop an automation","description":"Disables the automation **and** cancels every run still `running`. Stopping an automation that is already disabled still cancels its live runs, and still answers 200.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"responses":{"200":{"description":"The automation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopAutomationResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"automations:write"}},"/api/v1/automations/{automation_id}/versions":{"get":{"tags":["automations"],"summary":"List an automation's versions","description":"Every published version, newest first, with its graph and whether it is the active one. To make an earlier version active again, `PATCH /automations/{automation_id}` with that version's `steps` and `connections`: this publishes it as the next version.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"}],"responses":{"200":{"description":"The versions, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationVersionList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"automations:read"}},"/api/v1/automations/{automation_id}/runs":{"get":{"tags":["automations"],"summary":"Retrieve a list of automation runs","description":"One run per contact per enrolling event, newest first. A run parked on a `delay` is reported as `running`, and `?status=running` returns it, because the public status enum has no word for the difference.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"},{"schema":{"type":"string","description":"Filter runs by status. Comma-separated list of: running, completed, failed, cancelled. A run parked on a `delay` is reported as `running`."},"required":false,"description":"Filter runs by status. Comma-separated list of: running, completed, failed, cancelled. A run parked on a `delay` is reported as `running`.","name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Runs created before this are excluded."},"required":false,"description":"ISO 8601, inclusive. Runs created before this are excluded.","name":"start_date","in":"query"},{"schema":{"type":"string","description":"ISO 8601, inclusive. Runs created after this are excluded."},"required":false,"description":"ISO 8601, inclusive. Runs created after this are excluded.","name":"end_date","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAutomationRunsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"automations:read"}},"/api/v1/automations/{automation_id}/runs/{run_id}":{"get":{"tags":["automations"],"summary":"Retrieve a single automation run","description":"The run with its `steps[]` in **graph order** -- a breadth-first walk from the trigger of the version this run pinned, taking `condition_met` before `condition_not_met`, so a condition's two branches read in the order the editor draws them.","parameters":[{"schema":{"type":"string","description":"The ID of the automation.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"},"required":true,"description":"The ID of the automation.","name":"automation_id","in":"path"},{"schema":{"type":"string","description":"The ID of the automation run.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e02"},"required":true,"description":"The ID of the automation run.","name":"run_id","in":"path"}],"responses":{"200":{"description":"The run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationRun"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"automations:read"}},"/api/v1/events":{"post":{"tags":["events"],"summary":"Create an event","description":"Declares a custom event an automation may trigger on and `POST /events/send` may fire. Names are lower-case letters, digits, `.`, `_` and `-`, starting with a letter, unique among this team's live events, and never under the reserved `rasket:` prefix. An optional `schema` type-checks every payload sent under the name.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEventRequest"}}}},"responses":{"201":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEventResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"events:write"},"get":{"tags":["events"],"summary":"Retrieve a list of events","description":"Every live event definition, newest first. Items carry no `object`.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"1–100, default 20."},"required":false,"description":"1–100, default 20.","name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items after this ID."},"required":false,"description":"Return items after this ID.","name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255,"description":"Return items before this ID."},"required":false,"description":"Return items before this ID.","name":"before","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200,"description":"Case-insensitive substring of the events' names. `%` and `_` match literally."},"required":false,"description":"Case-insensitive substring of the events' names. `%` and `_` match literally.","name":"search","in":"query"}],"responses":{"200":{"description":"The page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEventsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"events:read"}},"/api/v1/events/send":{"post":{"tags":["events"],"summary":"Send an event","description":"Records the event against one contact and enrols them into every enabled automation triggering on it. Answers 202: the send is durable the moment this returns, and the runs start on the next tick. Exactly one of `contact_id` or `email` identifies the contact. There is no `Idempotency-Key` here -- two calls are two events and two runs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEventRequest"}}}},"responses":{"202":{"description":"The event was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEventResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"sending_access","x-rasket-scope":"events:send"}},"/api/v1/events/{identifier}":{"get":{"tags":["events"],"summary":"Retrieve a single event","description":"By ID or by name. `schema` is `null` when the event declares none.","parameters":[{"schema":{"type":"string","description":"The event ID (UUID) or event name.","example":"trial.started"},"required":true,"description":"The event ID (UUID) or event name.","name":"identifier","in":"path"}],"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"events:read"},"patch":{"tags":["events"],"summary":"Update an event","description":"Replaces the declared payload schema; `null` clears it. `schema` is required, because the only field a `PATCH` can change is that one -- an event's name is immutable, so that a version already triggering on it never loses its trigger.","parameters":[{"schema":{"type":"string","description":"The event ID (UUID) or event name.","example":"trial.started"},"required":true,"description":"The event ID (UUID) or event name.","name":"identifier","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEventRequest"}}}},"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEventResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"events:write"},"delete":{"tags":["events"],"summary":"Delete an event","description":"Soft-deletes and frees the name. A published automation version still naming it simply never fires again; runs already in flight are untouched.","parameters":[{"schema":{"type":"string","description":"The event ID (UUID) or event name.","example":"trial.started"},"required":true,"description":"The event ID (UUID) or event name.","name":"identifier","in":"path"}],"responses":{"200":{"description":"The removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveEventResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"events:write"}},"/api/v1/oauth/register":{"post":{"tags":["oauth"],"summary":"Register an OAuth client (RFC 7591)","description":"Unauthenticated dynamic client registration. Public clients only: `token_endpoint_auth_method` must be `none` and `response_types` must be `[\"code\"]`. Limited to 10 registrations per IP per hour and 1,000 a day platform-wide. The `registration_access_token` is shown exactly once and is the only credential for the management routes below.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":10,"description":"https URLs, or RFC 8252 §7.3 loopback URLs for a native client."},"client_name":{"type":"string","maxLength":100,"description":"Shown on the consent page. When omitted, the first https redirect URI's host."},"client_uri":{"type":"string","description":"https only; shown on the consent page."},"logo_uri":{"type":"string","description":"https only."},"scope":{"type":"string","description":"Space-separated, from: emails:send, emails:read, domains:read, domains:write, templates:read, templates:write, contacts:read, contacts:write, segments:read, segments:write, topics:read, topics:write, broadcasts:read, broadcasts:write, suppressions:read, suppressions:write, webhooks:read, webhooks:write, logs:read, automations:read, automations:write, events:read, events:write, events:send, team:read, team:write, billing:read, ai:use."},"grant_types":{"type":"array","items":{"type":"string"},"description":"Must include `authorization_code`. `refresh_token` is the only other grant kept; any other value is dropped."},"response_types":{"type":"array","items":{"type":"string","enum":["code"]}},"token_endpoint_auth_method":{"type":"string","description":"Always answered as `none`: every client is public. `client_secret_basic`, `client_secret_post` and `client_secret_jwt` are refused, because no secret is ever issued."},"software_id":{"type":"string"},"software_version":{"type":"string"}}}}}},"responses":{"201":{"description":"The registered client and its one-time token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisteredClient"}}}},"400":{"description":"RFC 7591 §3.2.2: the metadata was refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegistrationError"}}}},"429":{"description":"Too many registrations from this address, or platform-wide today.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/oauth/register/{client_id}":{"get":{"tags":["oauth"],"summary":"Read a registered client (RFC 7592)","description":"Requires `Authorization: Bearer <registration_access_token>`.","parameters":[{"schema":{"type":"string","description":"The `rkoc_` client identifier.","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"required":true,"description":"The `rkoc_` client identifier.","name":"client_id","in":"path"}],"responses":{"200":{"description":"The client's metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthClientInformation"}}}},"401":{"description":"Missing, malformed or unknown registration token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegistrationError"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"registrationAccessToken":[]}],"x-rasket-permission":"none","x-rasket-scope":null},"put":{"tags":["oauth"],"summary":"Replace a registered client's metadata (RFC 7592)","description":"A full replacement: a field the request omits is cleared. The registration access token is not rotated — a client has no channel to learn a new one.","parameters":[{"schema":{"type":"string","description":"The `rkoc_` client identifier.","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"required":true,"description":"The `rkoc_` client identifier.","name":"client_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":10,"description":"https URLs, or RFC 8252 §7.3 loopback URLs for a native client."},"client_name":{"type":"string","maxLength":100,"description":"Shown on the consent page. When omitted, the first https redirect URI's host."},"client_uri":{"type":"string","description":"https only; shown on the consent page."},"logo_uri":{"type":"string","description":"https only."},"scope":{"type":"string","description":"Space-separated, from: emails:send, emails:read, domains:read, domains:write, templates:read, templates:write, contacts:read, contacts:write, segments:read, segments:write, topics:read, topics:write, broadcasts:read, broadcasts:write, suppressions:read, suppressions:write, webhooks:read, webhooks:write, logs:read, automations:read, automations:write, events:read, events:write, events:send, team:read, team:write, billing:read, ai:use."},"grant_types":{"type":"array","items":{"type":"string"},"description":"Must include `authorization_code`. `refresh_token` is the only other grant kept; any other value is dropped."},"response_types":{"type":"array","items":{"type":"string","enum":["code"]}},"token_endpoint_auth_method":{"type":"string","description":"Always answered as `none`: every client is public. `client_secret_basic`, `client_secret_post` and `client_secret_jwt` are refused, because no secret is ever issued."},"software_id":{"type":"string"},"software_version":{"type":"string"}}}}}},"responses":{"200":{"description":"The replaced metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthClientInformation"}}}},"400":{"description":"RFC 7591 §3.2.2: the metadata was refused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegistrationError"}}}},"401":{"description":"Missing, malformed or unknown registration token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegistrationError"}}}},"429":{"description":"Too many registrations: a replacement that leaves the AI-client fast lane is charged as one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"registrationAccessToken":[]}],"x-rasket-permission":"none","x-rasket-scope":null},"delete":{"tags":["oauth"],"summary":"Delete a registered client (RFC 7592)","description":"Revokes every grant the client holds, on every team, with `revoked_reason = client`, and every token under them. The client row is kept as `disabled` so those grants keep their history; retention removes it later.","parameters":[{"schema":{"type":"string","description":"The `rkoc_` client identifier.","example":"rkoc_7Fq2Lm9pXw3Kd8Vn1Zt5Rb4C"},"required":true,"description":"The `rkoc_` client identifier.","name":"client_id","in":"path"}],"responses":{"204":{"description":"The client is deleted and its grants revoked."},"401":{"description":"Missing, malformed or unknown registration token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRegistrationError"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"registrationAccessToken":[]}],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/oauth/revoke":{"post":{"tags":["oauth"],"summary":"Revoke an access or refresh token","description":"An access token is revoked alone; a refresh token takes its whole family and every access token of the same grant (RFC 7009 §2.1). The grant itself stays live — only the customer or the client's deletion revokes that. A token that is unknown, expired, already revoked or another client's still answers **200** with an empty body (RFC 7009 §2.2).","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["token","client_id"],"properties":{"token":{"type":"string","description":"The access or refresh token to revoke."},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"],"description":"Accepted and ignored: one lookup finds either kind."},"client_id":{"type":"string","description":"The client the token was issued to."}}}},"application/json":{"schema":{"type":"object","required":["token","client_id"],"properties":{"token":{"type":"string","description":"The access or refresh token to revoke."},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"],"description":"Accepted and ignored: one lookup finds either kind."},"client_id":{"type":"string","description":"The client the token was issued to."}}}}}},"responses":{"200":{"description":"The token is revoked, or was never valid. Empty body."},"400":{"description":"The request was malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"`invalid_client`: unknown or disabled client.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"x-rasket-permission":"none","x-rasket-scope":null}},"/api/v1/oauth/grants":{"get":{"tags":["oauth"],"summary":"Retrieve a list of OAuth grants","description":"Every grant this team has given an OAuth client, newest first — live and revoked alike, so a revoked one is visible rather than silently gone.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"after","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":255},"required":false,"name":"before","in":"query"}],"responses":{"200":{"description":"A page of grants.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOAuthGrantsResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/oauth/grants/{oauth_grant_id}":{"delete":{"tags":["oauth"],"summary":"Revoke an OAuth grant","description":"Revokes the grant and every token issued under it, with `revoked_reason = user`. Idempotent: revoking a revoked grant answers the revocation it already has.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","description":"The OAuth grant ID.","example":"0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17"},"required":true,"description":"The OAuth grant ID.","name":"oauth_grant_id","in":"path"}],"responses":{"200":{"description":"The revoked grant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeOAuthGrantResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/mcp":{"post":{"tags":["mcp"],"summary":"The MCP endpoint","description":"A remote Model Context Protocol server in stateless JSON mode, authenticated by an OAuth access token. The body is a single JSON-RPC 2.0 request; a batch is refused. Accept must list both application/json and text/event-stream.","parameters":[{"schema":{"type":"string","description":"Comma-separated toolsets to register: `setup`, `send`, `audience`, `marketing`, `insight`, `ai`, `billing`. Absent means all seven; `describe_setup` is always registered. An unknown name is JSON-RPC error `-32602`.","example":"setup,send"},"required":false,"description":"Comma-separated toolsets to register: `setup`, `send`, `audience`, `marketing`, `insight`, `ai`, `billing`. Absent means all seven; `describe_setup` is always registered. An unknown name is JSON-RPC error `-32602`.","name":"toolset","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{}}}},"responses":{"200":{"description":"A JSON-RPC 2.0 response.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":null,"x-rasket-scope":null}},"/api/v1/team":{"get":{"tags":["team"],"summary":"The team this credential belongs to","description":"The team's profile, plan and limits, risk state, sender identity, brand kit, the rung of the sending ladder it holds and what unlocks the next one, whether AI assist is on, and a summary of its single sign-on connection. Never the SSO client secret, and never the member list (`GET /team/members`).","responses":{"200":{"description":"The team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamProfile"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"team:read"},"patch":{"tags":["team"],"summary":"Change the team's name, sender identity, AI assist or brand kit","description":"Every field is optional and at least one is required. `name` is the team's display name: it is trimmed, one line, 1 to 80 characters, and it does not have to be unique — the team's web address is set when the team is created and a rename does not change it. Renaming needs an admin, so a `full_access` key works and an OAuth token is `403 invalid_permission` whatever its scopes. `sender_name` and `postal_address` may be sent separately; each is paired with the value already stored, and a team with no postal address yet must send one. Each field sent writes an audit row (`team.renamed`, `team.postal_address_set`, `team.ai_assist_toggled`). `ai_assist_enabled: true` needs AI assist to be configured for this account and is `503 service_unavailable` when it is not; turning it off always works. `brand_kit` is the design your templates wear — a logo, two colours, a font, a button shape, a company name, an address and a footer line — and it is sent **whole**: every field is required and a field sent as `null` goes back to our default. Its values fill `{{brand.…}}` in a template and are never per-email data (`team.brand_kit_set`).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchTeamRequest"}}}},"responses":{"200":{"description":"The team after the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamProfile"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"AI assist is not available on this account: no provider is configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"team:write"}},"/api/v1/team/members":{"get":{"tags":["team"],"summary":"The people on the team","description":"A `full_access` API key or a session. No OAuth scope reaches this route: who is on a team is never shared with a connected app.","responses":{"200":{"description":"The team's members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/domains/{domain_id}/records":{"get":{"tags":["domains"],"summary":"Compare a domain's DNS records with what DNS answered","description":"Each record to publish, with its verification `status`, the values DNS answered at its `name` on the last check (`observed`), why it is not verified (`reason`) and when it was last checked. Use it to fix a domain that will not verify: a record with no `observed` value was not found, and one whose `observed` value differs from `value` was published wrong. Request a new check with `POST /domains/{domain_id}/verify`.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"d91cd9bd-1176-453e-8fc1-35364d380206"},"required":true,"name":"domain_id","in":"path"}],"responses":{"200":{"description":"The records and what DNS answered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRecords"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"domains:read"}},"/api/v1/emails/{email_id}/events":{"get":{"tags":["emails"],"summary":"List an email's delivery events","description":"Every event recorded for the email — sent, delivered, bounced, opened, clicked and the rest — oldest first, each with the recipient it is about (null for a whole-message event) and its event-specific `data`. Ordered by when the event happened, not by when it was received.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"The events, oldest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailEventList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"emails:read"}},"/api/v1/ai/subject-lines":{"post":{"tags":["ai"],"summary":"Suggest subject lines for an email","description":"Suggestions for the subject of the email described by `subject`, `html` and `text`. Nothing is saved. AI assist must be configured for this account (`503 service_unavailable` otherwise, before anything is recorded and at no cost), it must be on for the team (`403 invalid_permission`), the month's credits must not be spent (`422 validation_error`), and a team may make 10 AI requests a minute (`429 rate_limit_exceeded`). An accepted request spends one credit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSubjectLinesRequest"}}}},"responses":{"200":{"description":"The suggestions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiSubjectSuggestions"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"AI assist is not available on this account: no provider is configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"ai:use"}},"/api/v1/ai/draft":{"post":{"tags":["ai"],"summary":"Draft an email body from a brief","description":"An HTML and a plain-text body written from `brief`, or a rework of `existing_html`. Nothing is saved or sent. AI assist must be configured for this account (`503 service_unavailable` otherwise, before anything is recorded and at no cost), it must be on for the team (`403 invalid_permission`), the month's credits must not be spent (`422 validation_error`), and a team may make 10 AI requests a minute (`429 rate_limit_exceeded`). An accepted request spends one credit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiDraftRequest"}}}},"responses":{"200":{"description":"The draft.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiDraft"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"AI assist is not available on this account: no provider is configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"ai:use"}},"/api/v1/emails/{email_id}/diagnose":{"post":{"tags":["ai"],"summary":"Explain what happened to an email","description":"A summary of the email's delivery, its likely causes and next steps. The assistant sees recipient domains, statuses and the event timeline, never a recipient's address or the body. A diagnosis already made for the same state of the email is returned again with `stored: true` and costs nothing. An email that failed on our mail servers' side is answered with `cause: \"provider_failure\"` and its recorded reason, also at no cost. AI assist must be configured for this account (`503 service_unavailable` otherwise, before anything is recorded and at no cost), it must be on for the team (`403 invalid_permission`), the month's credits must not be spent (`422 validation_error`), and a team may make 10 AI requests a minute (`429 rate_limit_exceeded`). An accepted request spends one credit.","parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i","example":"4ef9a417-02e9-4d39-ad75-9611e0fcc33c"},"required":true,"name":"email_id","in":"path"}],"responses":{"200":{"description":"The diagnosis.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiDiagnosis"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"AI assist is not available on this account: no provider is configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-rasket-permission":"full_access","x-rasket-scope":"ai:use"}},"/api/v1/limits/requests":{"get":{"tags":["billing"],"summary":"List this project's limit requests","description":"A project can ask for a higher sending limit. An ask for a daily limit inside the band we grant automatically — at most twice what is in force, never past the ceiling of the project's sending tier, after its first week, and only while its delivery numbers are good — is approved the moment it is made and the new limit is in force immediately. Everything else, including any ask about a monthly allowance, is reviewed by a person and reports `pending`. A project whose sending is already being held down is declined, with the reason. This returns the project's own asks, newest first, with what became of each.","responses":{"200":{"description":"The asks this project has made, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitRequestList"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null},"post":{"tags":["billing"],"summary":"Ask for a higher sending limit","description":"A project can ask for a higher sending limit. An ask for a daily limit inside the band we grant automatically — at most twice what is in force, never past the ceiling of the project's sending tier, after its first week, and only while its delivery numbers are good — is approved the moment it is made and the new limit is in force immediately. Everything else, including any ask about a monthly allowance, is reviewed by a person and reports `pending`. A project whose sending is already being held down is declined, with the reason. Asking again while one is still under review answers with the ask already open rather than opening a second. An approval writes a `team.limits_raised_on_request` audit row and emails the project's admins.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitRequestCreate"}}}},"responses":{"201":{"description":"The ask, and what became of it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LimitRequest"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"A field or parameter is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":null}},"/api/v1/team/brand-kit/uploads":{"post":{"tags":["team"],"summary":"Upload an image for the brand kit's logo","description":"Stores a PNG, JPG or SVG and returns the stable HTTPS URL it is served at. This does not change your brand kit: send the `url` as `brand_kit.logo_url` in `PATCH /team` to use it. The type is read from the file itself. A PNG or JPG may be up to 256 KB and 4096 pixels on each side, and its EXIF, XMP and text metadata is removed before it is stored. An SVG may be up to 32 KB and may not contain script, links, animation or references to other files; nothing is repaired on the way in. Uploading the same file again returns the same URL. A file stays online after you replace or remove the logo, because emails you already sent still show it. A project can upload up to 100 different files.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1,"maxLength":1048576,"pattern":"^[A-Za-z0-9+/]+={0,2}$","description":"The image, base64-encoded: a PNG or JPG up to 256 KB and 4096 pixels on each side, or an SVG up to 32 KB with no script, links or references to other files. The type is read from the bytes."}},"required":["content"],"additionalProperties":false}}}},"responses":{"201":{"description":"The hosted file and the URL it is served at.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandKitUpload"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, unknown, or restricted API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is revoked or suspended, or the actor lacks the permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The file is not a PNG, JPG or SVG we can host, and `errors` carries one entry per reason. Also a project that has uploaded as many files as it may.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"There is nowhere to store a file, or no HTTPS origin to serve one from.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]},{"sessionCookie":[]}],"x-rasket-permission":"full_access","x-rasket-scope":"team:write"}}},"webhooks":{}}