{"openapi":"3.1.0","info":{"title":"tinysend API","version":"1.0.0","description":"REST API for tinysend — newsletter and email platform","contact":{"url":"https://tinysend.com"},"x-service-info":{"payments":{"protocol":"MPP","docs":"https://mpp.dev","pricing":"$0.003/email, $0.50 minimum","description":"Endpoints may return 402 with WWW-Authenticate header when plan limits are exceeded. MPP-capable agents can pay inline."},"categories":["email","newsletters","communications"],"docs":"https://tinysend.com/docs"}},"servers":[{"url":"https://api.tinysend.com/v1"}],"security":[{"Bearer":[]}],"components":{"securitySchemes":{"Bearer":{"type":"http","scheme":"bearer","description":"Bearer token (sk_*) from id.tinysend.com"}},"schemas":{"SubscriberSummary":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"status":{"type":"string"},"source":{"type":"string","nullable":true},"subscribed_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"waitlist_status":{"type":"string","nullable":true},"position":{"type":"integer","nullable":true}},"required":["id","email","name","status","source","subscribed_at","created_at"]},"SubscriberDetail":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"status":{"type":"string"},"source":{"type":"string","nullable":true},"subscribed_at":{"type":"string","nullable":true},"last_open_at":{"type":"string","nullable":true},"last_click_at":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","email","name","status","source","subscribed_at","last_open_at","last_click_at","country","city","created_at"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"ImportResult":{"type":"object","properties":{"imported":{"type":"integer"},"skipped":{"type":"integer"},"errors":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"reason":{"type":"string"}},"required":["email","reason"]}}},"required":["imported","skipped","errors"]},"PostSummary":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string"},"sent_at":{"type":"string","nullable":true},"recipients":{"type":"integer","nullable":true}},"required":["id","subject","status","created_at","sent_at","recipients"]},"PostDetail":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":"string"},"status":{"type":"string"},"body_html":{"type":"string","nullable":true},"body_text":{"type":"string","nullable":true},"issues_summary":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"Quality automation results (links, spelling, grammar)"},"checked_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"sent_at":{"type":"string","nullable":true},"stats":{"type":"object","properties":{"recipients":{"type":"integer"},"delivered":{"type":"integer"},"opened":{"type":"integer"},"clicked":{"type":"integer"},"bounced":{"type":"integer"}},"required":["recipients","delivered","opened","clicked","bounced"]}},"required":["id","subject","status","body_html","body_text","created_at","sent_at"]},"SendResult":{"type":"object","properties":{"status":{"type":"string"},"recipients":{"type":"integer"}},"required":["status","recipients"]},"SenderInfo":{"type":"object","properties":{"type":{"type":"string"},"from_address":{"type":"string"},"status":{"type":"string","enum":["default","pending","verified","failed"]},"records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordView"}},"next_step":{"type":"string"}},"required":["type","from_address","status","records","next_step"]},"DnsRecordView":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"value":{"type":"string"},"found":{"type":"boolean","description":"whether we can see this record in DNS yet"},"purpose":{"type":"string","description":"plain-words explanation of what the record does"}},"required":["type","name","value","found"]},"SiteDomainInfo":{"type":"object","properties":{"domain":{"type":"string","nullable":true},"default_url":{"type":"string"},"live_url":{"type":"string","nullable":true},"status":{"type":"string","enum":["not_configured","pending","active","failed"]},"records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordView"}},"next_step":{"type":"string","description":"plain-language description of what happens next / what the user needs to do"}},"required":["domain","default_url","live_url","status","records","next_step"]},"InviteResult":{"type":"object","properties":{"invited":{"type":"integer"}},"required":["invited"]},"InviteBody":{"type":"object","properties":{"count":{"type":"integer","minimum":1,"description":"Invite the next N entries by position.","example":100},"subscribers":{"type":"array","items":{"type":"string"},"description":"Invite these specific subscriber ids."},"all":{"type":"boolean","description":"Invite everyone still waiting (launch day)."}}},"WaitlistStats":{"type":"object","properties":{"total":{"type":"integer"},"waiting":{"type":"integer"},"invited":{"type":"integer"},"accepted":{"type":"integer"},"conversion_rate":{"type":"number"},"top_referrers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"referral_count":{"type":"integer"}},"required":["id","label","referral_count"]}}},"required":["total","waiting","invited","accepted","conversion_rate","top_referrers"]},"JoinResult":{"type":"object","properties":{"status":{"type":"string","enum":["created","exists","full","invalid"]},"subscriber_id":{"type":"string","nullable":true},"position":{"type":"integer","nullable":true},"referral_url":{"type":"string","nullable":true}},"required":["status","subscriber_id","position","referral_url"]},"JoinWaitlistBody":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Person joining by email (double opt-in). Omit to join as the authenticated agent identity."},"name":{"type":"string"},"ref":{"type":"string","description":"Referrer's referral code, to credit a referral."}}},"ListSummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subdomain":{"type":"string"},"type":{"type":"string"},"subscriber_count":{"type":"integer"},"sender_email":{"type":"string","nullable":true},"sender_domain_status":{"type":"string","nullable":true},"warmup_status":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","name","subdomain","type","subscriber_count","sender_email","sender_domain_status","warmup_status","created_at"]},"ListDetail":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"subdomain":{"type":"string"},"type":{"type":"string"},"description":{"type":"string","nullable":true},"subscriber_count":{"type":"integer"},"mailbox_id":{"type":"string","nullable":true},"mailbox_address":{"type":"string","nullable":true},"sender_name":{"type":"string","nullable":true},"sender_email":{"type":"string","nullable":true},"sender_domain":{"type":"string","nullable":true},"sender_domain_status":{"type":"string","nullable":true},"warmup_status":{"type":"string","nullable":true},"track_opens":{"type":"boolean","nullable":true},"track_clicks":{"type":"boolean","nullable":true},"show_posts":{"type":"boolean","nullable":true},"show_subscriber_count":{"type":"boolean","nullable":true},"created_at":{"type":"string"}},"required":["id","name","subdomain","type","description","subscriber_count","mailbox_id","mailbox_address","sender_name","sender_email","sender_domain","sender_domain_status","warmup_status","track_opens","track_clicks","show_posts","show_subscriber_count","created_at"]},"MailboxEmailSummary":{"type":"object","properties":{"id":{"type":"string"},"direction":{"type":"string"},"from_address":{"type":"string"},"to_address":{"type":"string"},"subject":{"type":"string","nullable":true},"status":{"type":"string"},"source_tag":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","direction","from_address","to_address","subject","status","source_tag","created_at"]},"MailboxEmailDetail":{"type":"object","properties":{"id":{"type":"string"},"direction":{"type":"string"},"from_address":{"type":"string"},"to_address":{"type":"string"},"subject":{"type":"string","nullable":true},"message_id":{"type":"string","nullable":true},"in_reply_to":{"type":"string","nullable":true},"r2_key":{"type":"string","nullable":true},"status":{"type":"string"},"handler_results":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"extracted_data":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"source_tag":{"type":"string","nullable":true},"contact_id":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","direction","from_address","to_address","subject","message_id","in_reply_to","r2_key","status","handler_results","extracted_data","source_tag","contact_id","created_at"]},"MailboxSummary":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"name":{"type":"string","nullable":true},"type":{"type":"string"},"status":{"type":"string"},"email_count":{"type":"integer"},"created_at":{"type":"string"}},"required":["id","address","name","type","status","email_count","created_at"]},"MailboxDetail":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"local_part":{"type":"string"},"domain":{"type":"string"},"name":{"type":"string","nullable":true},"type":{"type":"string"},"status":{"type":"string"},"list_id":{"type":"string","nullable":true},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"expires_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","address","local_part","domain","name","type","status","list_id","config","expires_at","created_at"]},"ContactSummary":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"total_received":{"type":"integer"},"total_opens":{"type":"integer"},"total_clicks":{"type":"integer"},"total_replies":{"type":"integer"},"list_count":{"type":"integer"},"last_activity_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","kind","email","name","country","city","total_received","total_opens","total_clicks","total_replies","list_count","last_activity_at","created_at"]},"ContactDetail":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"email":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"timezone":{"type":"string","nullable":true},"total_received":{"type":"integer"},"total_opens":{"type":"integer"},"total_clicks":{"type":"integer"},"total_replies":{"type":"integer"},"last_activity_at":{"type":"string","nullable":true},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","kind","email","name","notes","country","city","timezone","total_received","total_opens","total_clicks","total_replies","last_activity_at","created_at","updated_at"]},"ContactListMembership":{"type":"object","properties":{"list_id":{"type":"string"},"name":{"type":"string"},"subdomain":{"type":"string","nullable":true},"type":{"type":"string"},"status":{"type":"string"},"subscribed_at":{"type":"string","nullable":true}},"required":["list_id","name","subdomain","type","status","subscribed_at"]},"ContactActivityItem":{"type":"object","properties":{"kind":{"type":"string"},"at":{"type":"string"},"subject":{"type":"string"}},"required":["kind","at","subject"]},"ContactDeliveryItem":{"type":"object","properties":{"id":{"type":"string"},"post_id":{"type":"string","nullable":true},"subject":{"type":"string"},"list_name":{"type":"string"},"list_id":{"type":"string","nullable":true},"sent_at":{"type":"string"},"status":{"type":"string"},"open_count":{"type":"integer"},"click_count":{"type":"integer"}},"required":["id","post_id","subject","list_name","list_id","sent_at","status","open_count","click_count"]},"ProjectStats":{"type":"object","properties":{"lists":{"type":"integer"},"active_subscribers":{"type":"integer"},"contacts":{"type":"integer"},"emails_sent":{"type":"integer"}},"required":["lists","active_subscribers","contacts","emails_sent"]},"ListStats":{"type":"object","properties":{"subscribers":{"type":"object","properties":{"total":{"type":"integer"},"active":{"type":"integer"},"pending":{"type":"integer"},"unsubscribed":{"type":"integer"},"bounced":{"type":"integer"}},"required":["total","active","pending","unsubscribed","bounced"]},"deliveries":{"type":"object","properties":{"total_sent":{"type":"integer"},"total_delivered":{"type":"integer"},"total_opened":{"type":"integer"},"total_clicked":{"type":"integer"},"total_bounced":{"type":"integer"}},"required":["total_sent","total_delivered","total_opened","total_clicked","total_bounced"]}},"required":["subscribers","deliveries"]},"WebhookSummary":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"consecutive_failures":{"type":"integer"},"last_delivered_at":{"type":"string","nullable":true},"last_failed_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","url","events","status","consecutive_failures","last_delivered_at","last_failed_at","created_at"]},"WebhookCreated":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"secret":{"type":"string","description":"HMAC signing secret — shown only once"},"status":{"type":"string"},"created_at":{"type":"string"}},"required":["id","url","events","secret","status","created_at"]},"WebhookDetail":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"secret":{"type":"string","description":"Masked HMAC secret (only shown in full on creation)"},"status":{"type":"string"},"consecutive_failures":{"type":"integer"},"disabled_at":{"type":"string","nullable":true},"disabled_reason":{"type":"string","nullable":true},"last_delivered_at":{"type":"string","nullable":true},"last_failed_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","url","events","secret","status","consecutive_failures","disabled_at","disabled_reason","last_delivered_at","last_failed_at","created_at"]},"WebhookDeliveryItem":{"type":"object","properties":{"id":{"type":"string"},"event_type":{"type":"string"},"event_id":{"type":"string"},"http_status":{"type":"integer","nullable":true},"duration_ms":{"type":"integer","nullable":true},"attempt":{"type":"integer"},"status":{"type":"string"},"error":{"type":"string","nullable":true},"delivered_at":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["id","event_type","event_id","http_status","duration_ms","attempt","status","error","delivered_at","created_at"]},"TestWebhookResult":{"type":"object","properties":{"delivery_id":{"type":"string"},"status":{"type":"string"},"http_status":{"type":"integer","nullable":true},"duration_ms":{"type":"integer","nullable":true}},"required":["delivery_id","status","http_status","duration_ms"]},"Automation":{"type":"object","properties":{"id":{"type":"string"},"project_id":{"type":"string"},"type":{"type":"string"},"entity_type":{"type":"string"},"entity_id":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"system_prompt":{"type":"string","nullable":true},"tool_permissions":{"type":"object","nullable":true,"additionalProperties":{"type":"string"}},"schedule":{"type":"string","nullable":true},"skills":{"type":"array","nullable":true,"items":{"type":"string"}},"config":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"allowed_domains":{"type":"array","nullable":true,"items":{"type":"string"}},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","project_id","type","entity_type","entity_id","enabled","name","model","system_prompt","tool_permissions","schedule","skills","config","allowed_domains","created_at","updated_at"]},"CreateAutomation":{"type":"object","properties":{"project_id":{"type":"string","description":"Defaults to the caller's project when omitted."},"type":{"type":"string","enum":["quality","triage","auto_reply","digest","domain_health","spam_guard","audience","extract","otp","summarizer","custom"]},"entity_type":{"type":"string","enum":["mailbox","list","project"]},"entity_id":{"type":"string"},"enabled":{"type":"boolean"},"name":{"type":"string"},"model":{"type":"string"},"system_prompt":{"type":"string"},"tool_permissions":{"type":"object","additionalProperties":{"type":"string"}},"schedule":{"type":"string"},"skills":{"type":"array","items":{"type":"string"}},"config":{"type":"object","additionalProperties":{"nullable":true}},"allowed_domains":{"type":"array","items":{"type":"string"}}},"required":["type","entity_type","entity_id"]},"UpdateAutomation":{"type":"object","properties":{"enabled":{"type":"boolean"},"name":{"type":"string"},"model":{"type":"string","nullable":true},"system_prompt":{"type":"string","nullable":true},"tool_permissions":{"type":"object","additionalProperties":{"type":"string"}},"schedule":{"type":"string","nullable":true},"skills":{"type":"array","items":{"type":"string"}},"config":{"type":"object","additionalProperties":{"nullable":true}},"allowed_domains":{"type":"array","items":{"type":"string"}}}},"ProjectInvite":{"type":"object","properties":{"id":{"type":"string"},"project_id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"},"source":{"type":"string"},"created_at":{"type":"string"}},"required":["id","project_id","email","role","status","source","created_at"]}},"parameters":{}},"paths":{"/lists/{listId}/subscribers":{"get":{"tags":["Subscribers"],"summary":"List subscribers","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string","enum":["active","pending","unsubscribed","bounced"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Array of subscribers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SubscriberSummary"}}}}}},"operationId":"list_lists_subscribers"},"post":{"tags":["Subscribers"],"summary":"Add a subscriber","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"verified":{"type":"boolean","description":"Whether consent has already been verified. Default false: the subscriber is created 'pending' and a double opt-in confirmation email is sent — they become active only after clicking it. Set true ONLY when you have verified consent upstream (e.g. your own confirmed signup); the subscriber is then created 'active' with no confirmation email, attributed as verified via API.","example":false},"tags":{"type":"array","items":{"type":"string"},"description":"Person-level labels merged onto the contact (unioned with existing). Render in Apple Contacts as CATEGORIES.","example":["pro","from:better-auth"]},"metadata":{"type":"object","additionalProperties":{"nullable":true},"description":"Arbitrary per-person key/values, shallow-merged onto the contact. For segmentation/display.","example":{"plan":"pro","signup_source":"web"}},"org":{"type":"string","description":"Company — written to the contact."},"job_title":{"type":"string","description":"Role/title — written to the contact."}},"required":["email"]}}}},"responses":{"201":{"description":"Created subscriber","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberSummary"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_lists_subscribers"}},"/lists/{listId}/subscribers/{subId}":{"get":{"tags":["Subscribers"],"summary":"Get subscriber details","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"subId","in":"path"}],"responses":{"200":{"description":"Subscriber details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_lists_subscribers"},"patch":{"tags":["Subscribers"],"summary":"Update subscriber","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"subId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["active","unsubscribed"]}}}}}},"responses":{"200":{"description":"Updated subscriber","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriberSummary"}}}}},"operationId":"update_lists_subscribers"},"delete":{"tags":["Subscribers"],"summary":"Remove subscriber","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"subId","in":"path"}],"responses":{"204":{"description":"Deleted"}},"operationId":"delete_lists_subscribers"}},"/lists/{listId}/subscribers/import":{"post":{"tags":["Subscribers"],"summary":"Bulk import subscribers","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"subscribers":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"}},"required":["email"]}}},"required":["subscribers"]}}}},"responses":{"201":{"description":"Import results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}}},"operationId":"import_lists_subscribers"}},"/lists/{listId}/subscribers/export":{"get":{"tags":["Subscribers"],"summary":"Export subscribers as CSV","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"CSV file","content":{"text/csv":{"schema":{"type":"string"}}}}},"operationId":"list_lists_subscribers_export"}},"/lists/{listId}/posts":{"get":{"tags":["Posts"],"summary":"List posts","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Array of posts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PostSummary"}}}}}},"operationId":"list_lists_posts"},"post":{"tags":["Posts"],"summary":"Create a draft post","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"string","minLength":1},"body_html":{"type":"string"},"body_text":{"type":"string"}},"required":["subject"]}}}},"responses":{"201":{"description":"Created post","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDetail"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_lists_posts"}},"/lists/{listId}/posts/{postId}":{"get":{"tags":["Posts"],"summary":"Get post details with stats","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"postId","in":"path"}],"responses":{"200":{"description":"Post details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_lists_posts"},"patch":{"tags":["Posts"],"summary":"Update draft post","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"postId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"string"},"body_html":{"type":"string"},"body_text":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated post","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostDetail"}}}}},"operationId":"update_lists_posts"},"delete":{"tags":["Posts"],"summary":"Delete draft post","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"postId","in":"path"}],"responses":{"204":{"description":"Deleted"}},"operationId":"delete_lists_posts"}},"/lists/{listId}/posts/{postId}/send":{"post":{"tags":["Posts"],"summary":"Send post to all active subscribers","description":"Sends post to all active subscribers on the list. If sending would exceed the plan limit, returns 402 with MPP payment challenge (agents can pay inline) or upgrade URL.","x-payment-info":{"protocol":"MPP","docs":"https://mpp.dev","price":"$0.003/email, $0.50 minimum","description":"Metered operation. Sends beyond the plan limit return 402 with a WWW-Authenticate MPP challenge — agents can pay inline per overage email and retry."},"parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"postId","in":"path"}],"responses":{"202":{"description":"Sending started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendResult"}}}},"402":{"description":"Payment required — plan limit exceeded. Includes WWW-Authenticate header for MPP-capable agents.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"send_lists_posts"}},"/lists/{listId}/sender":{"get":{"tags":["Sender"],"summary":"Get sender configuration","description":"Who emails are sent from: tinysend default, your own domain, or gmail (coming soon). Includes DNS records with found/not-found status and a plain-language next step.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Sender info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_lists_sender"},"put":{"tags":["Sender"],"summary":"Set sender mode","description":"type=tinysend resets to the default. type=custom_domain needs name, email (local part), domain — creates the domain in Postmark and returns the DNS records to add. type=gmail is coming soon.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["tinysend","custom_domain","gmail"],"description":"tinysend = default @tinysend.com, custom_domain = your own domain via DNS, gmail = coming soon"},"name":{"type":"string","minLength":1,"example":"James"},"email":{"type":"string","minLength":1,"example":"james","description":"local part only, the bit before the @"},"domain":{"type":"string","minLength":1,"example":"acme.com"}},"required":["type"]}}}},"responses":{"200":{"description":"Sender updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"set_lists_sender"},"delete":{"tags":["Sender"],"summary":"Reset sender to tinysend default","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"204":{"description":"Reset to default"}},"operationId":"delete_lists_sender"}},"/lists/{listId}/sender/check":{"post":{"tags":["Sender"],"summary":"Re-check sender domain DNS now","description":"Triggers a fresh Postmark verification. The cron does this every minute anyway — use this for an immediate check after adding records.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Updated sender info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}}},"operationId":"check_lists_sender"}},"/lists/{listId}/site-domain":{"get":{"tags":["Site Domain"],"summary":"Get website domain status","description":"Custom domain for the public newsletter site. Includes the DNS records to add, found/not-found per record, and a plain-language next step. Verification and SSL run automatically every minute; the owner gets an email when the site is live.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Site domain info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDomainInfo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_lists_site_domain"},"post":{"tags":["Site Domain"],"summary":"Connect a custom domain","description":"Subdomains (news.acme.com) need one CNAME. Naked domains (acme.com) also get a TXT record for the security certificate and need ALIAS/flattened-CNAME support at the DNS provider; set www_enabled to serve www too.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","minLength":1,"example":"news.acme.com","description":"domain or subdomain you own"},"www_enabled":{"type":"boolean","description":"also serve www.<domain> (for naked domains)"}},"required":["domain"]}}}},"responses":{"201":{"description":"Domain added, records returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDomainInfo"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_lists_site_domain"},"delete":{"tags":["Site Domain"],"summary":"Disconnect the custom domain","description":"The site keeps working at its tinysend.com subdomain.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"204":{"description":"Removed"}},"operationId":"delete_lists_site_domain"}},"/lists/{listId}/site-domain/check":{"post":{"tags":["Site Domain"],"summary":"Re-check domain DNS and SSL now","description":"Triggers a fresh DNS + certificate check. The cron does this every minute anyway — use this for an immediate check after adding records.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Updated site domain info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDomainInfo"}}}}},"operationId":"check_lists_site_domain"}},"/lists/{listId}/domain":{"get":{"tags":["Sender"],"summary":"Get sender configuration","description":"Who emails are sent from: tinysend default, your own domain, or gmail (coming soon). Includes DNS records with found/not-found status and a plain-language next step.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Sender info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_lists_domain"},"put":{"tags":["Sender"],"summary":"Set sender mode","description":"type=tinysend resets to the default. type=custom_domain needs name, email (local part), domain — creates the domain in Postmark and returns the DNS records to add. type=gmail is coming soon.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","enum":["tinysend","custom_domain","gmail"],"description":"tinysend = default @tinysend.com, custom_domain = your own domain via DNS, gmail = coming soon"},"name":{"type":"string","minLength":1,"example":"James"},"email":{"type":"string","minLength":1,"example":"james","description":"local part only, the bit before the @"},"domain":{"type":"string","minLength":1,"example":"acme.com"}},"required":["type"]}}}},"responses":{"200":{"description":"Sender updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"set_lists_domain"},"delete":{"tags":["Sender"],"summary":"Reset sender to tinysend default","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"204":{"description":"Reset to default"}},"operationId":"delete_lists_domain"}},"/lists/{listId}/domain/check":{"post":{"tags":["Sender"],"summary":"Re-check sender domain DNS now","description":"Triggers a fresh Postmark verification. The cron does this every minute anyway — use this for an immediate check after adding records.","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Updated sender info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderInfo"}}}}},"operationId":"check_lists_domain"}},"/lists/{listId}/invite":{"post":{"tags":["Waitlist"],"summary":"Invite waitlist entries","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteBody"}}}},"responses":{"200":{"description":"Number invited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResult"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"invite_lists"}},"/lists/{listId}/stats":{"get":{"tags":["Waitlist"],"summary":"Waitlist stats","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"Stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistStats"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_lists_stats"}},"/lists/{listId}/join":{"post":{"tags":["Waitlist"],"summary":"Join a waitlist","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinWaitlistBody"}}}},"responses":{"200":{"description":"Join result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinResult"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"join_lists"}},"/lists":{"get":{"tags":["Lists"],"summary":"List all lists","responses":{"200":{"description":"Array of lists","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ListSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_lists"},"post":{"tags":["Lists"],"summary":"Create a list","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"type":{"type":"string","enum":["newsletter","waitlist","announcement"],"default":"newsletter"},"description":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"description":"Created list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDetail"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_lists"}},"/lists/{id}":{"get":{"tags":["Lists"],"summary":"Get list details","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"List details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_lists"},"patch":{"tags":["Lists"],"summary":"Update list settings","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"track_opens":{"type":"boolean"},"track_clicks":{"type":"boolean"},"show_posts":{"type":"boolean"},"show_subscriber_count":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDetail"}}}}},"operationId":"update_lists"},"delete":{"tags":["Lists"],"summary":"Delete a list","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"}},"operationId":"delete_lists"}},"/mailboxes/{mailboxId}/emails":{"get":{"tags":["Mailbox Emails"],"summary":"List emails","parameters":[{"schema":{"type":"string","enum":["inbound","outbound"]},"required":false,"name":"direction","in":"query"},{"schema":{"type":"string","enum":["received","read","replied","archived","failed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"source_tag","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Array of emails","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MailboxEmailSummary"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_mailboxes_emails"},"post":{"tags":["Mailbox Emails"],"summary":"Create outbound email","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"to_address":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1},"text_body":{"type":"string","minLength":1,"description":"Plain-text body. Sent via Cloudflare Email Service from the mailbox address."},"html_body":{"type":"string","description":"Optional HTML body."},"r2_key":{"type":"string"},"in_reply_to":{"type":"string"}},"required":["to_address","subject","text_body"]}}}},"responses":{"201":{"description":"Created email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxEmailDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_mailboxes_emails"}},"/mailboxes/{mailboxId}/emails/{emailId}":{"get":{"tags":["Mailbox Emails"],"summary":"Get email detail","parameters":[{"schema":{"type":"string"},"required":true,"name":"emailId","in":"path"}],"responses":{"200":{"description":"Email detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxEmailDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_mailboxes_emails"},"patch":{"tags":["Mailbox Emails"],"summary":"Update email status","parameters":[{"schema":{"type":"string"},"required":true,"name":"emailId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["read","archived"]}},"required":["status"]}}}},"responses":{"200":{"description":"Updated email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxEmailDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"update_mailboxes_emails"}},"/mailboxes":{"get":{"tags":["Mailboxes"],"summary":"List all mailboxes","responses":{"200":{"description":"Array of mailboxes","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MailboxSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_mailboxes"},"post":{"tags":["Mailboxes"],"summary":"Create a mailbox","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","minLength":1,"description":"Full email address (slug@domain). Optional for disposable mailboxes — a readable address (e.g. swift-otter@tinysend.com) is auto-generated when omitted."},"name":{"type":"string"},"type":{"type":"string","enum":["persistent","disposable","proxy"],"default":"persistent"},"config":{"type":"object","additionalProperties":{"nullable":true}},"ttl":{"anyOf":[{"type":"string"},{"type":"number"}],"description":"Lifetime for a disposable mailbox: a duration shorthand (\"1h\", \"24h\", \"7d\") or a number of seconds. Max 30 days. Alternative to expires_at; defaults to 24h."},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 expiry for disposable mailboxes (max 30 days out). Alternative to ttl."},"domain":{"type":"string","description":"Domain for an auto-generated disposable address. Defaults to tinysend.com."},"list_id":{"type":"string","description":"Link mailbox to existing list"}}}}}},"responses":{"201":{"description":"Created mailbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxDetail"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_mailboxes"}},"/mailboxes/{id}":{"get":{"tags":["Mailboxes"],"summary":"Get mailbox details","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Mailbox details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_mailboxes"},"patch":{"tags":["Mailboxes"],"summary":"Update mailbox settings","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"status":{"type":"string","enum":["active","paused","disabled"]},"config":{"type":"object","additionalProperties":{"nullable":true}},"expires_at":{"type":"string","nullable":true,"format":"date-time"}}}}}},"responses":{"200":{"description":"Updated mailbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxDetail"}}}}},"operationId":"update_mailboxes"},"delete":{"tags":["Mailboxes"],"summary":"Deactivate a mailbox","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deactivated"}},"operationId":"delete_mailboxes"}},"/emails":{"post":{"tags":["Emails"],"summary":"Send a transactional email","description":"One-off email to a single recipient, sent synchronously from a mailbox via the Postmark transactional stream. The from address must be an existing mailbox (root tinysend.com or a verified custom domain). Supports Idempotency-Key header — a repeated key returns the original send instead of sending twice.","x-payment-info":{"protocol":"MPP","docs":"https://mpp.dev","price":"$0.003/email, $0.50 minimum","description":"Metered operation. Sends beyond the plan limit return 402 with a WWW-Authenticate MPP challenge — agents can pay inline and retry."},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","format":"email","description":"Sending mailbox address. Optional with a mailbox-scoped key (defaults to its mailbox), required with a project-wide key.","example":"auth@tinysend.com"},"to":{"type":"string","format":"email","example":"user@example.com"},"subject":{"type":"string","minLength":1,"maxLength":998},"html":{"type":"string"},"text":{"type":"string"},"reply_to":{"type":"string","format":"email"},"tag":{"type":"string","maxLength":120,"description":"Free-form tag, filterable (stored as source_tag).","example":"auth.verification"},"metadata":{"type":"object","additionalProperties":{"type":"string"},"description":"User-controlled key-values, passed to Postmark and echoed in its webhooks (max ~10 fields)."}},"required":["to","subject"]}}}},"responses":{"200":{"description":"Duplicate Idempotency-Key — original send returned, nothing sent","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"subject":{"type":"string","nullable":true},"provider_message_id":{"type":"string","nullable":true},"created_at":{"type":"string","nullable":true}},"required":["id","status","from","to","subject","provider_message_id","created_at"]}}}},"201":{"description":"Email sent","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"subject":{"type":"string","nullable":true},"provider_message_id":{"type":"string","nullable":true},"created_at":{"type":"string","nullable":true}},"required":["id","status","from","to","subject","provider_message_id","created_at"]}}}},"402":{"description":"Plan limit exceeded — upgrade, enable overage, or pay inline via MPP","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation / mailbox / domain error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Provider rejected the send — safe to retry with the same Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_emails"}},"/emails/{emailId}":{"get":{"tags":["Emails"],"summary":"Get a transactional email","parameters":[{"schema":{"type":"string"},"required":true,"name":"emailId","in":"path"}],"responses":{"200":{"description":"Email","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"subject":{"type":"string","nullable":true},"provider_message_id":{"type":"string","nullable":true},"created_at":{"type":"string","nullable":true}},"required":["id","status","from","to","subject","provider_message_id","created_at"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_emails"}},"/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts for project","parameters":[{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["top","activity","name","email","created"],"default":"top"},"required":false,"name":"sort","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Array of contacts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContactSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_contacts"}},"/contacts/{id}":{"get":{"tags":["Contacts"],"summary":"Get contact details","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Contact details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_contacts"},"patch":{"tags":["Contacts"],"summary":"Update contact notes","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"notes":{"type":"string","description":"Freeform notes about this contact"}},"required":["notes"]}}}},"responses":{"200":{"description":"Updated contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"update_contacts"}},"/contacts/{id}/lists":{"get":{"tags":["Contacts"],"summary":"Lists this contact belongs to","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Array of list memberships","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContactListMembership"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_contacts_lists"}},"/contacts/{id}/activity":{"get":{"tags":["Contacts"],"summary":"Recent activity timeline for a contact","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Activity timeline","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContactActivityItem"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_contacts_activity"}},"/contacts/{id}/emails":{"get":{"tags":["Contacts"],"summary":"Emails delivered to this contact","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Delivery history","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContactDeliveryItem"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_contacts_emails"}},"/stats":{"get":{"tags":["Stats"],"summary":"Project-level aggregate stats","responses":{"200":{"description":"Project stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectStats"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_stats"}},"/stats/{listId}":{"get":{"tags":["Stats"],"summary":"Per-list aggregate stats","parameters":[{"schema":{"type":"string"},"required":true,"name":"listId","in":"path"}],"responses":{"200":{"description":"List stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListStats"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_stats"}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook subscriptions","responses":{"200":{"description":"Array of webhook subscriptions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_webhooks"},"post":{"tags":["Webhooks"],"summary":"Create a webhook subscription","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Public HTTPS URL to receive webhook POST requests"},"events":{"type":"array","items":{"type":"string","enum":["post.created","post.updated","post.sent","post.delivered","post.paused","post.resumed","post.cancelled","post.viewed","post.liked","email.received","email.sent","email.delivered","email.bounced","email.opened","email.clicked","email.complained","email.replied","subscriber.created","subscriber.confirmed","subscriber.unsubscribed","subscriber.deleted","contact.created","contact.updated","contact.deleted","contact_group.created","contact_group.updated","contact_group.deleted","list.created","list.updated","list.deleted","mailbox.created","mailbox.updated","mailbox.deleted","calendar_event.created","calendar_event.updated","calendar_event.deleted"]},"minItems":1,"description":"Event types to subscribe to"}},"required":["url","events"]}}}},"responses":{"201":{"description":"Created webhook (secret shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_webhooks"}},"/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Get webhook subscription details","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Webhook details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_webhooks"},"patch":{"tags":["Webhooks"],"summary":"Update a webhook subscription","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["post.created","post.updated","post.sent","post.delivered","post.paused","post.resumed","post.cancelled","post.viewed","post.liked","email.received","email.sent","email.delivered","email.bounced","email.opened","email.clicked","email.complained","email.replied","subscriber.created","subscriber.confirmed","subscriber.unsubscribed","subscriber.deleted","contact.created","contact.updated","contact.deleted","contact_group.created","contact_group.updated","contact_group.deleted","list.created","list.updated","list.deleted","mailbox.created","mailbox.updated","mailbox.deleted","calendar_event.created","calendar_event.updated","calendar_event.deleted"]},"minItems":1},"status":{"type":"string","enum":["active","paused"]}}}}}},"responses":{"200":{"description":"Updated webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDetail"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"update_webhooks"},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook subscription","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"delete_webhooks"}},"/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"Recent delivery log for a webhook","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Array of delivery attempts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryItem"}}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_webhooks_deliveries"}},"/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test event to the webhook","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Test delivery result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestWebhookResult"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"test_webhooks"}},"/automations":{"get":{"tags":["Automations"],"summary":"List automations","parameters":[{"schema":{"type":"string"},"required":true,"name":"project_id","in":"query"},{"schema":{"type":"string","enum":["mailbox","list","project"]},"required":false,"name":"entity_type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"entity_id","in":"query"}],"responses":{"200":{"description":"Automations list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Automation"}}},"required":["data"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_automations"},"post":{"tags":["Automations"],"summary":"Create automation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAutomation"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Automation"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_automations"}},"/automations/{id}":{"get":{"tags":["Automations"],"summary":"Get automation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Automation detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Automation"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"get_automations"},"patch":{"tags":["Automations"],"summary":"Update automation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAutomation"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Automation"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"update_automations"},"delete":{"tags":["Automations"],"summary":"Delete automation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"delete_automations"}},"/invites":{"get":{"tags":["Invites"],"summary":"List pending invites for the caller","responses":{"200":{"description":"Pending invites","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProjectInvite"}}},"required":["data"]}}}}},"operationId":"list_invites"}},"/invites/{id}/approve":{"post":{"tags":["Invites"],"summary":"Approve an invite","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInvite"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_invites_approve"}},"/invites/{id}/reject":{"post":{"tags":["Invites"],"summary":"Reject an invite","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectInvite"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_invites_reject"}},"/sdk/feedback":{"post":{"tags":["SDK"],"summary":"Submit in-app feedback (TinysendKit)","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"string","minLength":1,"maxLength":100,"description":"List subdomain the app belongs to"},"type":{"type":"string","enum":["problem","idea","question"]},"message":{"type":"string","minLength":1,"maxLength":10000},"email":{"type":"string","maxLength":320,"format":"email"},"appName":{"type":"string","minLength":1,"maxLength":100},"context":{"type":"object","properties":{"appVersion":{"type":"string","maxLength":50},"appBuild":{"type":"string","maxLength":50},"bundleId":{"type":"string","maxLength":200},"os":{"type":"string","maxLength":50},"osVersion":{"type":"string","maxLength":50},"device":{"type":"string","maxLength":100},"arch":{"type":"string","maxLength":20},"memoryGB":{"type":"string","maxLength":10},"freeDiskGB":{"type":"string","maxLength":10},"locale":{"type":"string","maxLength":20},"language":{"type":"string","maxLength":20}}},"extra":{"type":"object","additionalProperties":{"type":"string","maxLength":500}},"purchaseStatus":{"type":"string","enum":["paid","free"]},"appAccountToken":{"type":"string","format":"uuid"}},"required":["list","type","message"]}}}},"responses":{"200":{"description":"Feedback delivered to the app owner","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"List not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_sdk_feedback"}},"/sdk/subscribe":{"post":{"tags":["SDK"],"summary":"Subscribe an email to a list (TinysendKit, double opt-in)","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"list":{"type":"string","minLength":1,"maxLength":100,"description":"List subdomain to subscribe to"},"email":{"type":"string","maxLength":320,"format":"email"},"appName":{"type":"string","minLength":1,"maxLength":100},"bundleId":{"type":"string","maxLength":200},"appVersion":{"type":"string","maxLength":50},"os":{"type":"string","maxLength":50},"osVersion":{"type":"string","maxLength":50}},"required":["list","email"]}}}},"responses":{"200":{"description":"pending = confirmation email sent; already_subscribed = active subscriber exists","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","already_subscribed"]}},"required":["status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"List not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Unsupported list type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_sdk_subscribe"}},"/usage":{"get":{"tags":["Usage"],"summary":"Get current billing period usage","responses":{"200":{"description":"Usage info","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"period_start":{"type":"string"},"period_end":{"type":"string"},"emails_included":{"type":"number"},"emails_sent":{"type":"number"},"emails_remaining":{"type":"number"},"overage":{"type":"object","properties":{"enabled":{"type":"boolean"},"count":{"type":"number"},"rate":{"type":"number"},"cost":{"type":"number"},"cap":{"type":"number","nullable":true},"cap_remaining":{"type":"number","nullable":true}},"required":["enabled","count","rate","cost","cap","cap_remaining"]}},"required":["plan","period_start","period_end","emails_included","emails_sent","emails_remaining","overage"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_usage"}},"/settings/overage":{"get":{"tags":["Settings"],"summary":"Get overage billing settings","responses":{"200":{"description":"Overage settings","content":{"application/json":{"schema":{"type":"object","properties":{"overage_enabled":{"type":"boolean"},"overage_cap":{"type":"number","nullable":true},"overage_rate":{"type":"number"}},"required":["overage_enabled","overage_cap","overage_rate"]}}}},"404":{"description":"No project found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"list_settings_overage"},"post":{"tags":["Settings"],"summary":"Update overage billing settings","description":"Enable or disable overage billing. When enabling, a spending cap is required.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"overage_enabled":{"type":"boolean"},"overage_cap":{"type":"number","nullable":true,"minimum":0.5,"description":"Monthly spending cap in dollars. Minimum $0.50. Required when enabling overage."}},"required":["overage_enabled","overage_cap"]}}}},"responses":{"200":{"description":"Updated settings","content":{"application/json":{"schema":{"type":"object","properties":{"overage_enabled":{"type":"boolean"},"overage_cap":{"type":"number","nullable":true},"overage_rate":{"type":"number"}},"required":["overage_enabled","overage_cap","overage_rate"]}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_settings_overage"}},"/billing/subscribe":{"post":{"tags":["Billing"],"summary":"Subscribe to a plan via API","description":"Create a Stripe subscription programmatically. For agents with virtual cards or any API client that has a Stripe payment method. Pass a payment_method_id obtained from Stripe.js or the Stripe API.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["light","plus","max"],"description":"Plan to subscribe to"},"payment_method_id":{"type":"string","description":"Stripe payment method ID (pm_...)"}},"required":["plan","payment_method_id"]}}}},"responses":{"201":{"description":"Subscription created","content":{"application/json":{"schema":{"type":"object","properties":{"subscription_id":{"type":"string"},"plan":{"type":"string"},"status":{"type":"string"},"current_period_end":{"type":"string"}},"required":["subscription_id","plan","status","current_period_end"]}}}},"409":{"description":"Already subscribed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"operationId":"create_billing_subscribe"}},"/tools/disposable":{"get":{"tags":["Tools"],"summary":"Is a domain a disposable/throwaway email provider?","description":"Keyless. No API key required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"example.com","description":"A domain, email, or URL"},"required":true,"description":"A domain, email, or URL","name":"domain","in":"query"}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"},"disposable":{"type":"boolean"}},"required":["domain","disposable"]}}}},"422":{"description":"Invalid domain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"nullable":true}}}}}}},"operationId":"list_tools_disposable"}},"/tools/blacklist":{"get":{"tags":["Tools"],"summary":"Is a domain on email blacklists (Spamhaus/SURBL/URIBL)?","description":"Keyless. No API key required.","parameters":[{"schema":{"type":"string","minLength":1,"example":"example.com","description":"A domain, email, or URL"},"required":true,"description":"A domain, email, or URL","name":"domain","in":"query"}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"},"listed":{"type":"boolean"},"checked":{"type":"number"},"results":{"type":"array","items":{"type":"object","properties":{"zone":{"type":"string"},"status":{"type":"string"},"detail":{"type":"string"}},"required":["zone","status"]}}},"required":["domain","listed","checked","results"]}}}},"422":{"description":"Invalid domain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"nullable":true}}}}}}},"operationId":"list_tools_blacklist"}},"/tools/deliverability":{"get":{"tags":["Tools"],"summary":"Check SPF, DKIM, DMARC and MX for any domain","description":"Keyless. No API key required. Returns a 0-100 score and fix records.","parameters":[{"schema":{"type":"string","minLength":1,"example":"example.com","description":"A domain, email, or URL"},"required":true,"description":"A domain, email, or URL","name":"domain","in":"query"}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"},"spf":{"type":"object","properties":{"status":{"type":"string"},"record":{"type":"string","nullable":true}},"required":["status"]},"dkim":{"type":"object","properties":{"detected":{"type":"boolean"},"selectors":{"type":"array","items":{"type":"string"}}},"required":["detected","selectors"]},"dmarc":{"type":"object","properties":{"status":{"type":"string"},"record":{"type":"string","nullable":true},"policy":{"type":"string","nullable":true},"fix":{"type":"string"}},"required":["status","record","policy"]},"mx":{"type":"object","properties":{"status":{"type":"string"},"hosts":{"type":"array","items":{"type":"string"}}},"required":["status","hosts"]},"score":{"type":"number"}},"required":["domain","spf","dkim","dmarc","mx","score"]}}}},"422":{"description":"Invalid domain","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"nullable":true}}}}}}},"operationId":"list_tools_deliverability"}},"/tools/inbox-test":{"post":{"tags":["Tools"],"summary":"Create a spam-test inbox","description":"Keyless. Returns a one-time address; send a real email to it, then GET the result for a spam score.","responses":{"200":{"description":"Test inbox","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"}},"required":["id","address"]}}}}},"operationId":"create_tools_inbox_test"}},"/tools/inbox-test/{id}":{"get":{"tags":["Tools"],"summary":"Get spam-test result","description":"Keyless. Returns received=false until the email lands, then the spam score + report.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"address":{"type":"string"},"received":{"type":"boolean"},"report":{"type":"object","properties":{"score":{"type":"number"},"spf":{"type":"string"},"dkim":{"type":"string"},"dmarc":{"type":"string"},"flags":{"type":"array","items":{"type":"string"}}},"required":["score","spf","dkim","dmarc","flags"]}},"required":["id","address","received"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"nullable":true}}}}}}},"operationId":"get_tools_inbox_test"}}}}