{"openapi":"3.1.0","info":{"title":"Campaign Commander Agent API","version":"2026-10-11","description":"Political operations API for scoped keys. One server. Send Authorization: Bearer with a cc_live_ key. Paid actions execute directly when the key has the scope. Legacy approvals are optional. Every operation names its request and response fields. Responses do not include carrier identifiers."},"servers":[{"url":"https://www.campaigncommanderapp.com/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"agent"},{"name":"contacts"},{"name":"lists"},{"name":"suppressions"},{"name":"email"},{"name":"emails"},{"name":"sms"},{"name":"mail"},{"name":"voice"},{"name":"inbox"},{"name":"verification"},{"name":"communications"},{"name":"organization"},{"name":"team"},{"name":"profile"},{"name":"intake"},{"name":"team"},{"name":"registration"},{"name":"conversions"},{"name":"exports"},{"name":"audit-log"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"cc_live_","description":"Campaign Commander API key. Account, then Settings, then Agent API keys. Owners and admins can create a key. The secret is shown once."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in Campaign Commander wording."},"requiredScopes":{"type":"array","items":{"type":"string"}},"missingScopes":{"type":"array","items":{"type":"string"}},"retryAfter":{"type":"integer","description":"Seconds to wait after a 429."},"limit":{"type":"integer"},"resetAt":{"type":"string","format":"date-time"}},"additionalProperties":true,"example":{"error":"A valid Campaign Commander API key is required."}},"Success":{"type":"object","description":"A completed action.","additionalProperties":true},"ObjectBody":{"type":"object","description":"A JSON object. See the operation description for the fields that route accepts.","additionalProperties":true},"ApprovalOptional":{"type":"object","properties":{"approvalId":{"type":"string","description":"Optional legacy spend approval. Omit for direct execution."}},"additionalProperties":false},"TeamInvitationCreate":{"type":"object","required":["email","role"],"properties":{"email":{"type":"string","format":"email","description":"Invitee email address. Normalized to lower case."},"role":{"type":"string","enum":["admin","member","volunteer"],"description":"The role the invitee will hold if they accept."}},"additionalProperties":false,"example":{"email":"person@example.org","role":"member"}},"TeamMemberRoleUpdate":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["admin","member"],"description":"The member's new role. Promotion to owner is not accepted."}},"additionalProperties":false,"example":{"role":"admin"}},"TeamMemberNote":{"type":"object","properties":{"note":{"type":"string","description":"Optional note recorded on the team audit trail."}},"additionalProperties":false,"example":{"note":"On leave"}},"TeamInvitationResult":{"type":"object","additionalProperties":false,"required":["invitation","emailQueued","delivery"],"properties":{"invitation":{"type":"object","additionalProperties":false,"required":["id","email","role","status"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"],"format":"email"},"role":{"type":["string","null"]},"status":{"type":"string","enum":["pending","accepted","cancelled","dismissed"]},"created_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}},"description":"Safe invitation metadata only. No invite token, organization id, inviter, or whole row."},"emailQueued":{"type":"boolean","description":"True when a source email event was queued. NOT proof the email was sent or delivered."},"delivery":{"type":"string","enum":["queued"]},"note":{"type":"string"}}},"TeamInvitationAction":{"type":"object","additionalProperties":false,"required":["ok","invitationId"],"properties":{"ok":{"type":"boolean"},"invitationId":{"type":["string","null"],"format":"uuid"},"emailQueued":{"type":"boolean","description":"Present for a re-queue. NOT proof the email was sent or delivered."},"delivery":{"type":"string","enum":["queued"]},"note":{"type":"string"}}},"TeamMemberResult":{"type":"object","additionalProperties":false,"required":["ok","member"],"properties":{"ok":{"type":"boolean"},"member":{"type":"object","additionalProperties":false,"required":["id"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"],"format":"email"},"role":{"type":["string","null"]},"membership_status":{"type":["string","null"],"enum":["active","suspended","removed",null]}},"description":"Safe member metadata read back from the live membership. No whole user row."}}},"ScheduleBody":{"type":"object","required":["scheduledAt"],"properties":{"scheduledAt":{"type":"string","format":"date-time","description":"ISO-8601 with a numeric offset or Z. At least 5 minutes ahead and no more than 366 days out."},"approvalId":{"type":"string","description":"Optional legacy spend approval. Omit for direct execution."}},"additionalProperties":false,"example":{"scheduledAt":"2026-11-01T15:00:00Z"}},"Pagination":{"type":"object","required":["page","limit","total","hasMore"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"hasMore":{"type":"boolean"}}},"Contact":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uuid"},"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"],"description":"E.164 when the server stored one."},"address":{"type":["string","null"],"description":"Street address, trimmed. A partial address is allowed; a null address_hash is not a verification result."},"city":{"type":["string","null"],"description":"City, trimmed."},"state":{"type":["string","null"],"description":"State, trimmed and upper-cased."},"zip":{"type":["string","null"],"description":"ZIP code as text. A leading zero is kept."},"notes":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"custom_fields":{"type":"object","additionalProperties":{"type":"string"}},"email_opt_out":{"type":"boolean"},"email_opt_out_date":{"type":["string","null"],"format":"date-time"},"sms_opt_out":{"type":"boolean"},"sms_opt_out_date":{"type":["string","null"],"format":"date-time"},"do_not_contact":{"type":"boolean"},"dnc_reason":{"type":["string","null"]},"dnc_date":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"example":{"id":"8f3c2b10-6a1d-4e5f-9c20-0b7a1d2e3f40","first_name":"Ada","last_name":"Lovelace","email":"ada@example.com","phone":"+12025550147","tags":["volunteer"],"email_opt_out":false,"sms_opt_out":false,"do_not_contact":false}},"ContactWrite":{"type":"object","description":"At least one of first name, last name, email, phone, or a mailing-address field is required on create.","properties":{"firstName":{"type":["string","null"],"maxLength":120},"first_name":{"type":["string","null"],"maxLength":120},"lastName":{"type":["string","null"],"maxLength":120},"last_name":{"type":["string","null"],"maxLength":120},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"address":{"type":["string","null"],"description":"Street address. Trimmed. Omit to leave unchanged; null or an empty string clears it. A partial address is stored as-is; it is never reported as verified or deliverable."},"city":{"type":["string","null"],"description":"City. Trimmed. Omit to leave unchanged; null or an empty string clears it."},"state":{"type":["string","null"],"description":"State. Trimmed and upper-cased. Omit to leave unchanged; null or an empty string clears it."},"zip":{"type":["string","null"],"description":"ZIP code as text; a leading zero is kept. Omit to leave unchanged; null or an empty string clears it."},"notes":{"type":["string","null"]},"tags":{"type":"array","maxItems":25,"items":{"type":"string"}},"customFields":{"type":"object","additionalProperties":{"type":"string"}},"custom_fields":{"type":"object","additionalProperties":{"type":"string"}},"overrideSuppression":{"type":"boolean","description":"Required, with overrideNote, to add a suppressed email that the product allows an override for."},"overrideNote":{"type":"string","minLength":3}},"example":{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com","phone":"+12025550147"}},"ContactEnvelope":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/Contact"}},"additionalProperties":true},"ContactList":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"additionalProperties":true},"ContactSearchPagination":{"type":"object","required":["page","limit","total","hasMore"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":["integer","null"],"description":"Exact filtered count. null only when the database did not return a count, never a fabricated zero."},"hasMore":{"type":["boolean","null"],"description":"Whether another page exists. null means the exact count is unavailable, not that the list has ended; retry before assuming enumeration is complete."}}},"ContactSearchResult":{"description":"List mode returns a page of contacts with pagination; exact email/phone lookup returns a single contact.","oneOf":[{"type":"object","required":["contacts","pagination"],"properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"pagination":{"$ref":"#/components/schemas/ContactSearchPagination"}},"additionalProperties":true},{"$ref":"#/components/schemas/ContactEnvelope"}]},"TagWrite":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","minItems":1,"maxItems":25,"items":{"type":"string"}}},"example":{"tags":["volunteer"]}},"ConsentWrite":{"type":"object","properties":{"emailOptOut":{"type":"boolean"},"smsOptOut":{"type":"boolean"},"doNotContact":{"type":"boolean","description":"false is refused."}},"example":{"emailOptOut":true}},"ListFilters":{"type":"object","description":"Same filter object the product saves on a list.","properties":{"custom":{"type":"array","items":{"type":"object","additionalProperties":true}},"tags":{"type":"array","maxItems":25,"items":{"type":"string"}},"tagsAny":{"type":"array","items":{"type":"string"}},"state":{"type":"string"},"hasEmail":{"type":"boolean"},"hasPhone":{"type":"boolean"},"hasAddress":{"type":"boolean"},"excludeDNC":{"type":"boolean"},"excludeEmailOptOut":{"type":"boolean"}},"additionalProperties":true},"ListWrite":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"filters":{"$ref":"#/components/schemas/ListFilters"}},"example":{"name":"County volunteers","filters":{"hasEmail":true}}},"ListPreview":{"type":"object","required":["filters"],"properties":{"filters":{"$ref":"#/components/schemas/ListFilters"}}},"ListRecord":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":["string","null"]},"locked":{"type":"boolean"},"contact_count":{"type":"integer"},"description":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"filters":{"$ref":"#/components/schemas/ListFilters"}},"additionalProperties":true},"ListCollection":{"type":"object","required":["lists"],"properties":{"lists":{"type":"array","items":{"$ref":"#/components/schemas/ListRecord"}}}},"ListUsage":{"type":"object","required":["usage"],"properties":{"usage":{"type":"object","required":["emailCampaigns","smsCampaigns","mailCampaigns","voiceCampaigns","total"],"properties":{"emailCampaigns":{"type":"integer"},"smsCampaigns":{"type":"integer"},"mailCampaigns":{"type":"integer"},"voiceCampaigns":{"type":"integer"},"total":{"type":"integer"}}}}},"MemberIds":{"type":"object","required":["contactIds"],"properties":{"contactIds":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid"}}},"example":{"contactIds":["8f3c2b10-6a1d-4e5f-9c20-0b7a1d2e3f40"]}},"Suppression":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel":{"type":"string","enum":["email","sms","voice","all"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"reason":{"type":"string"},"consent_source":{"type":["string","null"]},"consent_timestamp":{"type":["string","null"],"format":"date-time"},"suppressed_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"SuppressionList":{"type":"object","required":["suppressions","pagination"],"properties":{"suppressions":{"type":"array","items":{"$ref":"#/components/schemas/Suppression"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"SuppressionWrite":{"type":"object","required":["reason","note"],"properties":{"email":{"type":"string","format":"email"},"phone":{"type":"string"},"reason":{"type":"string","enum":["manual","recipient_blocks_sender","unsubscribe","legal_request"]},"note":{"type":"string","minLength":3,"maxLength":1000}},"example":{"email":"ada@example.com","reason":"unsubscribe","note":"Asked to stop email on the phone."}},"SuppressionBypass":{"type":"object","required":["note"],"properties":{"note":{"type":"string","minLength":3,"maxLength":1000}}},"SuppressionEnvelope":{"type":"object","additionalProperties":true,"description":"The created email draft."},"EmailDraft":{"type":"object","properties":{"name":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string","description":"HTML body. html or body are accepted aliases."},"html":{"type":"string"},"body":{"type":"string"},"fromName":{"type":"string"},"fromEmail":{"type":"string","format":"email"},"replyToEmail":{"type":"string","format":"email"},"recipientType":{"type":"string","enum":["all","segment","selected","campaign_engagement"]},"segmentId":{"type":"string","format":"uuid"},"segmentIds":{"type":"array","items":{"type":"string","format":"uuid"}},"selectedContactIds":{"type":"array","items":{"type":"string","format":"uuid"}},"sourceCampaignId":{"type":"string","format":"uuid"},"engagement":{"type":"string","enum":["opened","clicked"]},"engagementInclude":{"type":"string","enum":["human","all"]},"excludeCampaignIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Prior email campaigns. People on them are left out, once per contact."},"resendToNonOpenersAfterHours":{"description":"24 or true turns on a next-day send to people who did not open. false or null leaves it off."},"firstNameFallback":{"type":["string","null"],"description":"Greeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins."},"scheduledAt":{"type":"string","format":"date-time","description":"Optional. Also schedules the new draft. Requires email:send and Idempotency-Key."}},"example":{"name":"Rally follow-up","subject":"Thanks for coming","message":"<p>See you next week.</p>","recipientType":"all"}},"EmailDraftPatch":{"type":"object","properties":{"name":{"type":"string"},"subject":{"type":"string"},"message":{"type":"string"},"html":{"type":"string"},"body":{"type":"string"},"fromName":{"type":"string"},"fromEmail":{"type":"string","format":"email"},"replyToEmail":{"type":"string","format":"email"},"firstNameFallback":{"type":["string","null"],"description":"Greeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to leave the saved value. Null or blank clears it back to Friend. An inline tag still wins."}}},"EmailPreview":{"type":"object","properties":{"ready":{"type":"boolean"},"blockers":{"type":"array","items":{"type":"string"}},"audience":{"type":"object","properties":{"recipientType":{"type":"string"},"uniqueRecipients":{"type":"integer"},"recipientCount":{"type":"integer"},"excludedCount":{"type":"integer"},"accountSuppressedCount":{"type":"integer","description":"Addresses skipped because they are already blocked for this account."},"message":{"type":["string","null"]}},"additionalProperties":true},"cost":{"type":"object","properties":{"estimatedCostCents":{"type":"integer"},"balanceCents":{"type":"integer"},"canAfford":{"type":"boolean"}}}},"additionalProperties":true},"EmailCreateResult":{"type":"object","properties":{"success":{"type":"boolean"},"campaignId":{"type":"string","format":"uuid"},"recipients":{"type":"integer"},"uniqueRecipients":{"type":"integer"},"costInCents":{"type":"integer"}},"additionalProperties":true},"EmailSendResult":{"type":"object","properties":{"success":{"type":"boolean"},"queued":{"type":"boolean"},"status":{"type":"string"}},"additionalProperties":true},"EmailTest":{"type":"object","properties":{"to":{"description":"One address or a list of up to 5. Each must be the key owner, an active member, or a verified test recipient."},"testEmails":{"type":"array","maxItems":5,"items":{"type":"string","format":"email"}}}},"TransactionalSend":{"type":"object","required":["to"],"properties":{"to":{"description":"Required. One address or a list. Combined to, cc, and bcc must be 1 to 50."},"cc":{},"bcc":{},"from":{"type":"string"},"reply_to":{"type":"string"},"subject":{"type":"string","maxLength":998},"html":{"type":"string"},"text":{"type":"string"},"template_id":{"type":"string","format":"uuid"},"variables":{"type":"object","additionalProperties":true},"headers":{"type":"object","additionalProperties":{"type":"string"}},"tags":{"type":"array","maxItems":10,"items":{"type":"string"}},"tracking":{"type":"boolean","default":false}},"example":{"to":"ada@example.com","subject":"Your receipt","text":"Thanks for your gift."}},"TransactionalAccepted":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"}},"additionalProperties":true},"ConversionWrite":{"type":"object","required":["campaignId","event","externalId"],"properties":{"campaignId":{"type":"string","format":"uuid"},"event":{"type":"string","pattern":"^[a-z][a-z0-9_-]{0,79}$"},"externalId":{"type":"string"},"valueCents":{"type":"integer","minimum":0},"occurredAt":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":true}},"example":{"campaignId":"8f3c2b10-6a1d-4e5f-9c20-0b7a1d2e3f40","event":"donation","externalId":"gift-1001","valueCents":2500}},"VerificationQuote":{"type":"object","properties":{"uniqueToCheck":{"type":"integer"},"costCents":{"type":"integer"},"resourceId":{"type":"string"},"balanceCents":{"type":"integer"},"configured":{"type":"boolean","description":"Whether email or address verification is turned on. This is not a vendor name."}},"additionalProperties":true},"SmsDraft":{"type":"object","properties":{"type":{"type":"string","enum":["sms","mms"]},"name":{"type":"string","maxLength":120},"message":{"type":"string","maxLength":1600},"recipientType":{"type":"string","enum":["all","segment","custom"]},"segmentId":{"type":"string","format":"uuid"},"segmentIds":{"type":"array","items":{"type":"string","format":"uuid"}},"filters":{"$ref":"#/components/schemas/ListFilters"}},"example":{"type":"sms","name":"Rally reminder","message":"Doors open at 6.","recipientType":"all"}},"SmsCampaign":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string","enum":["sms","mms"]},"status":{"type":"string"},"message":{"type":"string"},"hasMedia":{"type":"boolean"},"totalRecipients":{"type":"integer"},"sentCount":{"type":"integer"},"failedCount":{"type":"integer"},"deliveredCount":{"type":"integer"},"estimatedCostCents":{"type":"integer"},"actualSpendCents":{"type":"integer"},"scheduledAt":{"type":["string","null"],"format":"date-time"}},"additionalProperties":true},"SmsCampaignEnvelope":{"type":"object","properties":{"success":{"type":"boolean"},"status":{"type":"string"},"campaign":{"$ref":"#/components/schemas/SmsCampaign"}},"additionalProperties":true},"SmsCampaignList":{"type":"object","additionalProperties":true,"description":"Text campaigns for this organization."},"SmsOutcomes":{"type":"object","properties":{"outcomes":{"type":"object","properties":{"failed":{"type":"integer"},"skipped":{"type":"integer"},"failuresByReason":{"type":"array","items":{"type":"object","properties":{"reason":{"type":"string","enum":["landline","invalid_destination","unreachable_sms","carrier_reject","region_blocked","sender_unregistered","suppressed","unknown"]},"count":{"type":"integer"},"sampleError":{"type":["string","null"],"description":"Plain language. Carrier text is not returned."},"autoSuppressed":{"type":"boolean"}}}}}}},"additionalProperties":true},"VoiceDraft":{"type":"object","required":["type","name","ccNumberId","recipientType"],"properties":{"type":{"type":"string","enum":["call","voicemail"]},"name":{"type":"string","maxLength":160},"message":{"type":"string","description":"Required when type is call."},"ccNumberId":{"type":"string"},"recipientType":{"type":"string","enum":["all","segment","custom"]},"segmentId":{"type":"string","format":"uuid"},"contactIds":{"type":"array","items":{"type":"string","format":"uuid"}},"audioAssetToken":{"type":"string","description":"Required for voicemail. From the upload route."},"audioDuration":{"type":"integer","minimum":1,"maximum":300}}},"VoiceDraftResult":{"type":"object","additionalProperties":false,"description":"A voice draft was saved. Nothing was dialed.","properties":{"success":{"type":"boolean"},"status":{"type":"string","const":"draft"},"providerSubmitted":{"type":"boolean","const":false},"campaignId":{"type":"string","format":"uuid"}},"required":["success","status","providerSubmitted"],"example":{"success":true,"status":"draft","providerSubmitted":false}},"VoiceAsset":{"type":"object","additionalProperties":false,"description":"A voicemail file token. The storage location is not returned. Pass assetToken when creating the campaign. audioUrl is optional.","properties":{"success":{"type":"boolean","const":true},"assetToken":{"type":"string","description":"Opaque token. It does not contain a storage URL."},"acceptedTypes":{"type":"array","items":{"type":"string"}},"maxDurationSeconds":{"type":"integer","const":300}},"required":["success","assetToken","maxDurationSeconds"],"example":{"success":true,"assetToken":"v2.example","acceptedTypes":["audio/mpeg","audio/wav"],"maxDurationSeconds":300}},"VoiceCallCreate":{"type":"object","required":["contactId"],"properties":{"contactId":{"type":"string","format":"uuid"},"approvalId":{"type":"string"}}},"PowerDialerOpen":{"type":"object","required":["campaignId"],"properties":{"campaignId":{"type":"string","format":"uuid"}}},"AgentRun":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"objective":{"type":"string"},"summary":{"type":["string","null"]},"status":{"type":"string","enum":["active","waiting_for_master","needs_input","completed","cancelled"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}},"additionalProperties":true},"AgentRunList":{"type":"object","additionalProperties":true},"AgentRunCreate":{"type":"object","required":["objective"],"properties":{"objective":{"type":"string","minLength":3,"maxLength":500},"summary":{"type":"string","maxLength":2000}}},"AgentRunUpdate":{"type":"object","properties":{"status":{"type":"string","enum":["active","waiting_for_master","needs_input","completed","cancelled"]},"summary":{"type":"string","maxLength":2000}}},"Capabilities":{"type":"object","properties":{"apiVersion":{"type":"string"},"agent":{"type":"object","additionalProperties":true},"endpoints":{"type":"object","additionalProperties":{"type":"string"}},"pricing":{"type":"object","additionalProperties":true}},"additionalProperties":true,"description":"Authenticated. Prices are customer prices."},"CommunicationSettings":{"type":"object","properties":{"organization":{"type":"object","additionalProperties":true},"email":{"type":"object","additionalProperties":true,"description":"From name, from address, reply-to, and a domain status label. DNS records are not returned."},"compliance":{"type":"object","additionalProperties":true}},"additionalProperties":true},"OrganizationSettingsFields":{"type":"object","additionalProperties":false,"description":"The reviewed organization-settings allowlist. Verification tokens, fingerprints, and provider identifiers are never returned.","properties":{"committeeName":{"type":["string","null"]},"authorizationLine":{"type":["string","null"]},"physicalAddressStreet":{"type":["string","null"]},"physicalAddressStreet2":{"type":["string","null"]},"physicalAddressCity":{"type":["string","null"]},"physicalAddressState":{"type":["string","null"]},"physicalAddressZip":{"type":["string","null"]},"optionalContact":{"type":["string","null"]},"replyToEmail":{"type":["string","null"]},"emailFromName":{"type":["string","null"]},"emailFromAddress":{"type":["string","null"]},"organizationType":{"type":["string","null"]},"ein":{"type":["string","null"]},"legalBusinessName":{"type":["string","null"]},"website":{"type":["string","null"]},"defaultCampaignPhoneId":{"type":["string","null"]},"sendingDomain":{"type":["string","null"]},"campaignVerifyProvided":{"type":"boolean"},"campaignVerifyImported":{"type":"boolean"},"campaignVerifyEmailProvided":{"type":"boolean"},"updatedAt":{"type":["string","null"]}},"required":["committeeName","authorizationLine","physicalAddressStreet","physicalAddressCity","physicalAddressState","physicalAddressZip","replyToEmail","emailFromName","emailFromAddress","organizationType","campaignVerifyProvided","campaignVerifyImported","campaignVerifyEmailProvided"]},"OrganizationSettingsSetup":{"type":"object","additionalProperties":false,"properties":{"complete":{"type":"boolean"},"missing":{"type":"array","items":{"type":"string"}}},"required":["complete","missing"]},"OrganizationSettings":{"type":"object","additionalProperties":false,"properties":{"organization":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"status":{"type":["string","null"]}},"required":["id","name","status"]},"settings":{"anyOf":[{"$ref":"#/components/schemas/OrganizationSettingsFields"},{"type":"null"}]},"setup":{"$ref":"#/components/schemas/OrganizationSettingsSetup"},"role":{"type":["string","null"]},"canEditSettings":{"type":"boolean"}},"required":["organization","settings","setup","role","canEditSettings"]},"OrganizationSettingsUpdate":{"type":"object","additionalProperties":false,"required":["committeeName","authorizationLine","physicalAddressStreet","physicalAddressCity","physicalAddressState","physicalAddressZip","emailFromName","emailFromAddress","replyToEmail","organizationType"],"properties":{"committeeName":{"type":"string"},"authorizationLine":{"type":"string"},"physicalAddressStreet":{"type":"string"},"physicalAddressStreet2":{"type":"string"},"physicalAddressCity":{"type":"string"},"physicalAddressState":{"type":"string"},"physicalAddressZip":{"type":"string"},"optionalContact":{"type":"string"},"replyToEmail":{"type":"string"},"emailFromName":{"type":"string"},"emailFromAddress":{"type":"string"},"organizationType":{"type":"string","enum":["candidate","pac","party","other_527","501c3","501c4","501c5","501c6"]},"ein":{"type":"string"},"legalBusinessName":{"type":"string"},"website":{"type":"string"},"defaultCampaignPhoneId":{"type":"string"},"campaignVerifyToken":{"type":"string"},"campaignVerifyEmailToken":{"type":"string"}},"example":{"committeeName":"Friends of Ada","authorizationLine":"Paid for by Friends of Ada","physicalAddressStreet":"1 Main St","physicalAddressCity":"Polk City","physicalAddressState":"FL","physicalAddressZip":"33868","emailFromName":"Friends of Ada","emailFromAddress":"send@example.org","replyToEmail":"reply@example.org","organizationType":"candidate"}},"OrganizationSettingsSave":{"type":"object","additionalProperties":false,"properties":{"settings":{"anyOf":[{"$ref":"#/components/schemas/OrganizationSettingsFields"},{"type":"null"}]},"changedFields":{"type":"array","items":{"type":"string"}},"setup":{"$ref":"#/components/schemas/OrganizationSettingsSetup"}},"required":["settings","changedFields","setup"]},"PersonalSettingsFields":{"type":"object","additionalProperties":false,"description":"The credential owner's own personal profile and preferences. User-wide: these belong to the person across every organization they belong to. Values preserve a legitimate word that is also a supplier's name (an ordinary name in a full name or signature is not rewritten).","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"],"description":"Read-only. Login email is not changed here."},"fullName":{"type":["string","null"]},"personalPhone":{"type":["string","null"]},"personalPhoneE164":{"type":["string","null"],"description":"Read-only normalized phone."},"timezone":{"type":["string","null"]},"country":{"type":["string","null"]},"defaultFromName":{"type":["string","null"]},"defaultFromEmail":{"type":["string","null"]},"defaultReplyToEmail":{"type":["string","null"]},"defaultSmsSignature":{"type":["string","null"]},"quietHoursEnabled":{"type":"boolean"},"quietHoursStart":{"type":["string","null"]},"quietHoursEnd":{"type":["string","null"]},"optInMethods":{"type":"array","items":{"type":"string"},"description":"Saved preferences, not recipient-consent evidence."},"optInDescription":{"type":["string","null"]},"billingContactEmail":{"type":["string","null"]},"lowBalanceThresholdCents":{"type":["integer","null"],"description":"Alert threshold in whole cents, not a spending limit."},"usageNotificationsEnabled":{"type":"boolean"},"dailySpendAlertsEnabled":{"type":"boolean"}},"required":["id","email","fullName","personalPhone"]},"PersonalSettings":{"type":"object","additionalProperties":false,"properties":{"profile":{"anyOf":[{"$ref":"#/components/schemas/PersonalSettingsFields"},{"type":"null"}]}},"required":["profile"],"example":{"profile":{"id":"11111111-1111-4111-8111-111111111111","email":"owner@example.org","fullName":"Ada Lovelace","personalPhone":"+18635550101","personalPhoneE164":"+18635550101","timezone":"America/New_York","country":"US","quietHoursEnabled":false,"quietHoursStart":"21:00:00","quietHoursEnd":"09:00:00","optInMethods":[],"lowBalanceThresholdCents":500,"usageNotificationsEnabled":true,"dailySpendAlertsEnabled":false}}},"PersonalSettingsUpdate":{"type":"object","additionalProperties":false,"description":"An allowlisted patch of the credential owner's own personal profile and preferences. Only the keys you send are changed; an omitted field keeps its stored value and an empty string or null clears a string field.","properties":{"fullName":{"type":["string","null"]},"personalPhone":{"type":["string","null"]},"timezone":{"type":["string","null"]},"country":{"type":["string","null"]},"defaultFromName":{"type":["string","null"]},"defaultFromEmail":{"type":["string","null"]},"defaultReplyToEmail":{"type":["string","null"]},"defaultSmsSignature":{"type":["string","null"]},"quietHoursEnabled":{"type":"boolean"},"quietHoursStart":{"type":["string","null"]},"quietHoursEnd":{"type":["string","null"]},"optInMethods":{"type":["array","null"],"items":{"type":"string"}},"optInDescription":{"type":["string","null"]},"billingContactEmail":{"type":["string","null"]},"lowBalanceThresholdCents":{"type":"integer","minimum":0},"usageNotificationsEnabled":{"type":"boolean"},"dailySpendAlertsEnabled":{"type":"boolean"}},"example":{"fullName":"Ada Lovelace","timezone":"America/New_York","lowBalanceThresholdCents":0,"usageNotificationsEnabled":false}},"PersonalSettingsSave":{"type":"object","additionalProperties":false,"properties":{"profile":{"anyOf":[{"$ref":"#/components/schemas/PersonalSettingsFields"},{"type":"null"}]},"changedFields":{"type":"array","items":{"type":"string"}}},"required":["profile","changedFields"]},"BrandSubmitRequest":{"type":"object","additionalProperties":false,"required":["fee_acknowledged"],"description":"The same brand fields as the preview, plus the fee acknowledgement. Send the same fields to POST /agent/approvals first when this key requires an operator approval, then pass the returned id as approvalId.","properties":{"legal_business_name":{"type":"string","description":"Legal business name. Omit to use the saved value."},"ein":{"type":"string","description":"Nine-digit EIN. Omit to use the saved value."},"street_address":{"type":"string"},"street_address2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"postal_code":{"type":"string"},"website":{"type":"string","description":"Send an empty string to clear it; omit to use the saved value."},"authorized_rep_name":{"type":"string"},"authorized_rep_email":{"type":"string","format":"email"},"authorized_rep_phone":{"type":"string"},"fee_acknowledged":{"type":"boolean","const":true,"description":"Must be true: acknowledges the non-refundable one-time brand filing fee."},"approvalId":{"type":"string","description":"Optional spend approval id for a key that requires an operator to approve each filing."}},"example":{"fee_acknowledged":true}},"BrandSubmitResult":{"type":"object","additionalProperties":true,"required":["fee_charged_cents"],"properties":{"success":{"type":"boolean"},"already_filed":{"type":"boolean","description":"True when a matching filing is already on file; fee_charged_cents is then 0."},"brand_status":{"type":"string"},"fee_charged_cents":{"type":"integer","description":"The non-refundable one-time brand filing fee that was charged."},"filing_reconciliation_required":{"type":"boolean","description":"An uncertain carrier outcome. Do not resubmit; contact support."},"idempotency_conflict":{"type":"boolean","description":"The key was reused with different business information. Refresh before a new submission."},"message":{"type":"string"}}},"BrandRegistrationFee":{"type":"object","additionalProperties":false,"required":["brand_registration_cents"],"properties":{"brand_registration_cents":{"type":"integer","description":"One-time, non-refundable brand filing fee in cents."}}},"BrandRegistrationEligibility":{"type":"object","additionalProperties":false,"required":["owner_and_setup_eligible","reason"],"properties":{"owner_and_setup_eligible":{"type":"boolean","description":"Role-and-setup eligibility only: the credential is the active, fully-set-up organization owner. It is not a grant of spending authority and does not mean a paid submission is available."},"reason":{"type":"string","description":"Plain-language reason. Not a carrier name."}}},"BrandRegistrationFiling":{"type":"object","additionalProperties":false,"required":["status","already_filed","has_carrier_reference","verified","rejected","submitting","confirmation_required"],"properties":{"registration_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"Locally stored filing state."},"already_filed":{"type":"boolean","description":"A nonempty carrier reference plus a post-submission state. Not true for a draft or an unknown status."},"has_carrier_reference":{"type":"boolean","description":"Whether a carrier brand reference is stored (the value itself is never returned)."},"verified":{"type":"boolean"},"rejected":{"type":"boolean"},"submitting":{"type":"boolean","description":"A stored submission is still in flight."},"confirmation_required":{"type":"boolean","description":"A prior paid filing may be with the carrier unconfirmed. Do not resubmit."},"submitted_at":{"type":["string","null"],"format":"date-time"}}},"BrandRegistrationStatus":{"type":"object","additionalProperties":false,"required":["source","brand_status","fee","eligibility","setup"],"properties":{"source":{"type":"string","enum":["local"],"description":"The status is stored locally, not a live carrier reconciliation."},"note":{"type":"string"},"submission_note":{"type":"string","description":"States that paid brand submission requires registration:submit."},"organization":{"type":"object","additionalProperties":true},"brand_status":{"type":"string"},"filing":{"anyOf":[{"$ref":"#/components/schemas/BrandRegistrationFiling"},{"type":"null"}]},"fee":{"$ref":"#/components/schemas/BrandRegistrationFee"},"balance_cents":{"type":"integer"},"eligibility":{"$ref":"#/components/schemas/BrandRegistrationEligibility"},"setup":{"type":"object","additionalProperties":false,"required":["complete"],"properties":{"complete":{"type":"boolean"}}}}},"BrandPreviewRequest":{"type":"object","additionalProperties":false,"properties":{"legal_business_name":{"type":"string","description":"Legal business name. Omit to use the saved value."},"ein":{"type":"string","description":"Nine-digit EIN. Omit to use the saved value."},"street_address":{"type":"string"},"street_address2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"postal_code":{"type":"string"},"website":{"type":"string","description":"Send an empty string to clear it; omit to use the saved value."},"authorized_rep_name":{"type":"string"},"authorized_rep_email":{"type":"string","format":"email"},"authorized_rep_phone":{"type":"string"}}},"BrandPreview":{"type":"object","additionalProperties":false,"required":["ready","missing_fields","fee","eligibility","setup"],"properties":{"source":{"type":"string","enum":["local"]},"note":{"type":"string"},"submission_note":{"type":"string","description":"States that paid brand submission requires registration:submit."},"ready":{"type":"boolean","description":"Whether the supplied packet passes the same field validation the dashboard submit uses. Packet validity only; it is not a statement about filing state, role permission, or a sufficient balance."},"problem":{"type":["string","null"],"description":"The first required fix, or null when ready."},"missing_fields":{"type":"array","items":{"type":"string"}},"organization":{"type":"object","additionalProperties":true},"brand_status":{"type":"string"},"already_filed":{"type":"boolean"},"confirmation_required":{"type":"boolean"},"fee":{"$ref":"#/components/schemas/BrandRegistrationFee"},"balance_cents":{"type":"integer"},"eligibility":{"$ref":"#/components/schemas/BrandRegistrationEligibility"},"setup":{"type":"object","additionalProperties":false,"required":["complete"],"properties":{"complete":{"type":"boolean"}}}}},"CampaignRegistrationFiling":{"type":"object","additionalProperties":false,"required":["status","already_filed","has_carrier_reference","rejected","retryable","confirmation_required","submitting"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"Locally stored campaign filing state."},"use_case":{"type":["string","null"],"description":"The registered traffic use case."},"is_current":{"type":"boolean"},"submission_number":{"type":["integer","null"]},"rejection_reason":{"type":["string","null"],"description":"Carrier rejection text when the filing was rejected."},"submitted_at":{"type":["string","null"],"format":"date-time"},"approved_at":{"type":["string","null"],"format":"date-time"},"has_carrier_reference":{"type":"boolean","description":"Whether a carrier campaign reference is stored (the value itself is never returned)."},"already_filed":{"type":"boolean","description":"True exactly when a carrier campaign reference is recorded. It means an identity is stored, not approval, delivery, or a charge. False means no recorded reference, not proof that the carrier received nothing."},"rejected":{"type":"boolean"},"retryable":{"type":"boolean","description":"A rejected filing may be corrected and resubmitted (with or without a recorded carrier reference). False when the attempt is unconfirmed (confirmation_required) or still in progress (submitting), matching the paid route's reconciliation precedence. Not a fee receipt."},"confirmation_required":{"type":"boolean","description":"An existing local attempt cannot be interpreted with confidence (an explicit unconfirmed-outcome marker, an unrecognized/missing status, an unrecognized submission-state marker, or an active-looking status with no carrier reference). Do not submit another filing; reconcile it. This does not establish whether a fee was charged."},"submitting":{"type":"boolean","description":"Explicitly stored as in progress (submission_state 'submitting'). Not proof the process is alive and not a charge claim."},"campaign_verify_imported_at":{"type":["string","null"],"format":"date-time"},"opt_in_description":{"type":["string","null"],"description":"Your own opt-in copy (frozen filed flow, else the current draft)."},"sample_message_1":{"type":["string","null"],"description":"Your own sample message (frozen filed sample, else the current draft)."},"filed_opt_in_url":{"type":["string","null"]},"filed_privacy_url":{"type":["string","null"]},"filed_terms_url":{"type":["string","null"]},"filed_screenshot_url":{"type":["string","null"]},"filed_message_flow":{"type":["string","null"]},"filed_sample_1":{"type":["string","null"]}}},"CampaignDraft":{"type":"object","additionalProperties":false,"properties":{"opt_in_method":{"type":["string","null"]},"opt_in_description":{"type":["string","null"]},"opt_in_url":{"type":["string","null"]},"privacy_policy_url":{"type":["string","null"]},"terms_url":{"type":["string","null"]},"opt_in_screenshot_url":{"type":["string","null"]}}},"SiteCheckHistoryEntry":{"type":"object","additionalProperties":false,"required":["ok","failed_labels"],"properties":{"id":{"type":"string","format":"uuid"},"event_type":{"type":["string","null"]},"ok":{"type":"boolean"},"failed_labels":{"type":"array","items":{"type":"string"}},"opt_in_url":{"type":["string","null"]},"privacy_url":{"type":["string","null"]},"terms_url":{"type":["string","null"]},"checked_at":{"type":["string","null"],"format":"date-time"}}},"CampaignRegistrationStatus":{"type":"object","additionalProperties":false,"required":["source","campaign_status","filing","draft","site_check_history","last_site_check","fee","setup"],"properties":{"source":{"type":"string","enum":["local"],"description":"The status is stored locally, not a live carrier reconciliation."},"note":{"type":"string"},"submission_note":{"type":"string","description":"States that paid campaign filing requires registration:submit."},"site_check_note":{"type":"string"},"organization":{"type":"object","additionalProperties":true},"campaign_status":{"type":"string","description":"The organization-level campaign status label."},"filing":{"anyOf":[{"$ref":"#/components/schemas/CampaignRegistrationFiling"},{"type":"null"}]},"draft":{"anyOf":[{"$ref":"#/components/schemas/CampaignDraft"},{"type":"null"}]},"organization_type":{"type":["string","null"]},"last_site_check":{"anyOf":[{"$ref":"#/components/schemas/SiteCheckHistoryEntry"},{"type":"null"}]},"site_check_history":{"type":"array","items":{"$ref":"#/components/schemas/SiteCheckHistoryEntry"}},"fee":{"type":"object","additionalProperties":false,"required":["campaign_review_cents"],"properties":{"campaign_review_cents":{"type":"integer","description":"Non-refundable campaign review fee in cents."}}},"balance_cents":{"type":"integer"},"setup":{"type":"object","additionalProperties":false,"required":["complete"],"properties":{"complete":{"type":"boolean"}}}}},"CampaignSiteCheckRequest":{"type":"object","additionalProperties":false,"required":["opt_in_url","privacy_policy_url","terms_url"],"properties":{"opt_in_url":{"type":"string","description":"Public https URL of the SMS opt-in form on your campaign website."},"privacy_policy_url":{"type":"string"},"terms_url":{"type":"string"},"opt_in_screenshot_url":{"type":"string"}}},"CampaignSiteCheckResult":{"type":"object","additionalProperties":false,"required":["source","recorded","checked_at","ok","failed_labels","opt_in","privacy","terms"],"properties":{"source":{"type":"string","enum":["local"]},"note":{"type":"string"},"recorded":{"type":"boolean","description":"Whether the history row was durably appended. It is never true when the append failed."},"checked_at":{"type":"string","format":"date-time"},"ok":{"type":"boolean"},"failed_labels":{"type":"array","items":{"type":"string"}},"opt_in":{"type":"array","items":{"type":"object","additionalProperties":true}},"privacy":{"type":"array","items":{"type":"object","additionalProperties":true}},"terms":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"CampaignSiteCheckFailure":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"ok":{"type":"boolean","enum":[false],"description":"Always false on a failed preflight."},"recorded":{"type":"boolean","enum":[false],"description":"Whether a durable history row was appended. False on every failure path: the check is never presented as durable evidence."},"code":{"type":"string","enum":["invalid_packet","fetch_failed","history_failed"],"description":"Machine-readable failure. invalid_packet: the URL packet failed validation and no page was fetched. fetch_failed: the live pages could not be loaded. history_failed: the pages were checked but the history row could not be written, so the result is not durable."},"error":{"type":"string","description":"Human-readable failure text."},"outcome":{"type":"object","additionalProperties":true,"description":"Present only when the pages WERE fetched (history_failed): the same safe ok/failedLabels/optIn/privacy/terms checklist as the success body, so a caller knows the check ran but was not recorded."}}},"CampaignDraftRequest":{"type":"object","additionalProperties":false,"properties":{"opt_in_url":{"type":"string","description":"Public https URL of the SMS opt-in form on your campaign website. An empty string clears the saved value."},"privacy_policy_url":{"type":"string","description":"Public https URL of the privacy policy. An empty string clears the saved value."},"terms_url":{"type":"string","description":"Public https URL of the terms of service. An empty string clears the saved value."},"opt_in_screenshot_url":{"type":"string","description":"Optional public https URL of an opt-in screenshot. An empty string clears the saved value."},"opt_in_description":{"type":"string","description":"How a person opts in. It must name the form, privacy, and terms URLs plus STOP and HELP, or it is refused. An empty string clears the saved value."},"help_email":{"type":"string","format":"email","description":"Optional HELP reply contact. A supplied value must be a valid address, and an empty value never erases the stored shared inbox."},"expected_volume":{"type":"string","description":"Optional expected monthly message volume."}}},"CampaignDraftSaved":{"type":"object","additionalProperties":false,"required":["source","saved","saved_fields"],"properties":{"source":{"type":"string","enum":["local"]},"note":{"type":"string"},"saved":{"type":"boolean","const":true,"description":"True only when the draft was durably written. A failed write is an error, never a false success."},"saved_fields":{"type":"array","items":{"type":"string"},"description":"The stored column names that were written. The draft copy itself is not echoed."}}},"CampaignSubmitRequest":{"type":"object","additionalProperties":false,"required":["compliance_acknowledged","fee_acknowledged","confirm"],"properties":{"compliance_acknowledged":{"type":"boolean","const":true,"description":"Must be true: acknowledges the messaging compliance requirements of the filing."},"fee_acknowledged":{"type":"boolean","const":true,"description":"Must be true on a fresh filing: acknowledges the non-refundable review fee charged for this submission. A retry on an already-charged filing skips it."},"confirm":{"type":"boolean","const":true,"description":"Must be true: confirms the filing itself. The review fee is non-refundable per submission."},"idempotency_key":{"type":"string","description":"Optional here: the bounded Idempotency-Key header is the canonical form. A repeat with the same key is already on file and charges nothing."},"help_email":{"type":"string","format":"email","description":"Optional HELP reply contact for this filing. Omit to use the saved one."},"campaign_verify_token":{"type":"string","description":"Optional Campaign Verify token for a political organization that needs one. Omit to use the saved token."},"approval_id":{"type":"string","description":"Optional spend approval id for a key that requires an operator to approve each filing."}},"example":{"compliance_acknowledged":true,"fee_acknowledged":true,"confirm":true}},"CampaignSubmitResult":{"type":"object","additionalProperties":true,"required":["success"],"properties":{"success":{"type":"boolean"},"already_submitted":{"type":"boolean","description":"True when an existing filing attempt is already on file. No new review fee is charged."},"already_filed":{"type":"boolean","description":"True when a carrier campaign reference is already recorded for this organization."},"campaign_status":{"type":"string","description":"queued when the business registration is not yet approved, draft when the carrier returned no reference, otherwise submitted."},"fee_charged_cents":{"type":"integer","description":"The non-refundable review fee charged for this submission, or 0 when nothing was charged."},"filing_reconciliation_required":{"type":"boolean","description":"An uncertain carrier outcome or an unrecordable result. Do not resubmit; contact support."},"message":{"type":"string"}}},"PhoneNumberSearchResults":{"type":"object","additionalProperties":false,"required":["numbers"],"properties":{"numbers":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["phoneNumber","cost","monthlyCost"],"properties":{"phoneNumber":{"type":"string","description":"An E.164 number available to buy."},"formattedNumber":{"type":"string","description":"The same number formatted for display."},"cost":{"type":"string","description":"One-time setup price in dollars, as a string."},"monthlyCost":{"type":"string","description":"Monthly rental in dollars, as a string."},"features":{"type":"array","items":{"type":"string"},"description":"Capabilities the number supports."},"region":{"type":"string","description":"Toll-Free, or the local region name."},"isTollFree":{"type":"boolean","description":"True for a toll-free number."}}}}}},"PhoneNumberPurchaseRequest":{"type":"object","additionalProperties":false,"required":["phoneNumber","confirm"],"properties":{"phoneNumber":{"type":"string","description":"The toll-free number to buy, in E.164 form."},"confirm":{"type":"boolean","description":"Must be true. A purchase spends the setup fee and cannot be undone."},"approvalId":{"type":"string","description":"Optional operator approval id for this exact purchase."}},"example":{"phoneNumber":"+180****0100","confirm":true}},"PhoneNumberPurchaseResult":{"type":"object","additionalProperties":false,"required":["success"],"properties":{"success":{"type":"boolean"},"already_purchased":{"type":"boolean","description":"True when a retry with the same key matched a completed purchase."},"phoneNumber":{"type":"string","description":"The purchased number, when known."},"orderId":{"type":"string","description":"The carrier order reference for support. Not a customer-facing id."}}},"PhoneNumberDefaultResult":{"type":"object","additionalProperties":false,"required":["success"],"properties":{"success":{"type":"boolean"},"id":{"type":"string","description":"The number id that is now the default."}}},"CallingQueues":{"type":"object","additionalProperties":false,"description":"The prepared calling queues this member may work in the credential's organization, plus this member's own active or paused shift session id per queue. The campaign list is organization-wide, not an individual assignment; only the shift session id is personal. A pending_count of null means the count could not be read (unavailable), not zero. truncated reports whether more campaigns could exist than were read; shiftsTruncated reports whether this member's own shift page was capped, so a null session_id is not proof of no open shift.","properties":{"campaigns":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"pending_count":{"type":["integer","null"],"minimum":0},"session_id":{"type":["string","null"]}},"required":["id","name","status","pending_count","session_id"]}},"truncated":{"type":"boolean"},"shiftsTruncated":{"type":"boolean"}},"required":["campaigns","truncated","shiftsTruncated"],"example":{"campaigns":[{"id":"11111111-1111-4111-8111-111111111111","name":"Evening calls","status":"sending","pending_count":12,"session_id":null}],"truncated":false,"shiftsTruncated":false}},"CallingPhone":{"type":"object","additionalProperties":false,"description":"The persisted result of saving the credential owner's own operator phone. Only whether a phone was set and its last four digits are returned.","properties":{"phone":{"type":"object","additionalProperties":false,"properties":{"set":{"type":"boolean"},"lastFour":{"type":"string"}},"required":["set","lastFour"]}},"required":["phone"],"example":{"phone":{"set":true,"lastFour":"0177"}}},"CallingPhoneUpdate":{"type":"object","additionalProperties":false,"description":"The only field accepted when saving your own operator phone. A caller-supplied user or organization selector is refused.","properties":{"phone":{"type":"string","description":"Your operator phone as a U.S. number. Normalized but not verified."}},"required":["phone"],"example":{"phone":"+18635550101"}},"OpenApiDocument":{"type":"object","additionalProperties":false,"description":"This OpenAPI document. The same JSON is served at /openapi.json.","properties":{"openapi":{"type":"string","const":"3.1.0"},"info":{"type":"object","additionalProperties":true},"servers":{"type":"array","items":{"type":"object","additionalProperties":true}},"paths":{"type":"object","additionalProperties":true}},"required":["openapi","info","paths"],"example":{"openapi":"3.1.0","info":{"title":"Campaign Commander Agent API","version":"1.0.0"},"paths":{}}},"Approval":{"type":"object","additionalProperties":false,"description":"A single-use legacy spend approval bound to this key.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","approved","expired","consumed","rejected"]},"action":{"type":"string"},"resource_type":{"type":"string","nullable":true},"resource_id":{"type":"string","nullable":true},"max_cents":{"type":"integer","minimum":0,"description":"Whole cents."},"max_units":{"type":"integer","nullable":true},"requested_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time"},"approved_at":{"type":"string","format":"date-time","nullable":true},"consumed_at":{"type":"string","format":"date-time","nullable":true},"agent_run_id":{"type":"string","nullable":true},"approved_by":{"type":["string","null"],"description":"standing limit when this key's standing spend limit granted the approval. Null when a person approved it or it is still pending. The key id is api_key_id."},"api_key_id":{"type":"string","format":"uuid","description":"Key that requested the spend. Recorded with approved_by standing limit."}},"required":["id","status","action","max_cents","requested_at","expires_at"],"example":{"id":"11111111-1111-4111-8111-111111111111","status":"approved","action":"email_campaign.send","resource_type":"email_campaign","resource_id":null,"max_cents":500,"max_units":null,"requested_at":"2026-10-11T18:00:00Z","expires_at":"2026-10-11T19:00:00Z","approved_at":"2026-10-11T18:05:00Z","consumed_at":null,"agent_run_id":null,"approved_by":"standing limit","api_key_id":"22222222-2222-4222-8222-222222222222"}},"ApprovalList":{"type":"object","additionalProperties":false,"description":"Legacy approvals for this key only.","properties":{"approvals":{"type":"array","items":{"$ref":"#/components/schemas/Approval"}}},"required":["approvals"],"example":{"approvals":[]}},"ApprovalRequest":{"type":"object","additionalProperties":false,"description":"Optional request for a legacy spend approval. Paid actions do not wait on this. For registration.brand.submit, send `brand` with the same brand fields the submit call will use and omit resourceId; the owner approves the server-derived packet hash, so the same fields must be sent again at execution.","properties":{"action":{"type":"string","minLength":1,"maxLength":120,"example":"email_campaign.send"},"maxCents":{"type":"integer","minimum":1,"example":500},"resourceType":{"type":"string"},"resourceId":{"type":"string"},"agentRunId":{"type":"string","maxLength":200},"brand":{"$ref":"#/components/schemas/BrandPreviewRequest"}},"required":["action"],"example":{"action":"email_campaign.send","resourceId":"55555555-5555-4555-8555-555555555555","maxCents":500}},"Deleted":{"type":"object","additionalProperties":false,"description":"The row was removed or the action completed.","properties":{"success":{"type":"boolean","const":true}},"required":["success"],"example":{"success":true}},"MemberChange":{"type":"object","additionalProperties":false,"description":"How many static-list memberships changed.","properties":{"success":{"type":"boolean"},"added":{"type":"integer","minimum":0},"removed":{"type":"integer","minimum":0}},"required":["success"],"example":{"success":true,"added":2}},"ListResolve":{"type":"object","additionalProperties":false,"description":"One matching list, or candidates when the name is ambiguous.","properties":{"match":{"type":"object","nullable":true,"additionalProperties":true},"candidates":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["candidates"],"example":{"match":null,"candidates":[]}},"ListCount":{"type":"object","additionalProperties":false,"description":"A count only. Contacts are not returned.","properties":{"count":{"type":"integer","minimum":0}},"required":["count"],"example":{"count":1280}},"InboxConversation":{"type":"object","additionalProperties":false,"description":"Inbox triage row. Delivery addresses are omitted.","properties":{"id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","format":"uuid","nullable":true},"channel":{"type":"string","enum":["sms","email"]},"subject":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","closed"]},"last_message_at":{"type":"string","format":"date-time","nullable":true},"last_message_preview":{"type":"string","nullable":true},"unread_count":{"type":"integer","minimum":0},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"contact":{"type":"object","nullable":true,"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}}}},"required":["id","channel","status"],"example":{"id":"22222222-2222-4222-8222-222222222222","channel":"sms","status":"active","unread_count":1}},"InboxList":{"type":"object","additionalProperties":false,"description":"Conversations for triage.","properties":{"conversations":{"type":"array","items":{"$ref":"#/components/schemas/InboxConversation"}}},"required":["conversations"],"example":{"conversations":[]}},"InboxMessage":{"type":"object","additionalProperties":false,"description":"One message. Phone numbers and email addresses are omitted.","properties":{"id":{"type":"string","format":"uuid"},"channel":{"type":"string","enum":["sms","email"]},"direction":{"type":"string","enum":["inbound","outbound"]},"content":{"type":"string","nullable":true},"subject":{"type":"string","nullable":true},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","channel","direction"],"example":{"id":"33333333-3333-4333-8333-333333333333","channel":"sms","direction":"inbound","content":"Can you call me?"}},"InboxDetail":{"type":"object","additionalProperties":false,"description":"One conversation and its recent messages.","properties":{"conversation":{"$ref":"#/components/schemas/InboxConversation"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/InboxMessage"}}},"required":["conversation","messages"],"example":{"conversation":{"id":"22222222-2222-4222-8222-222222222222","channel":"sms","status":"active"},"messages":[]}},"SuppressionRow":{"type":"object","additionalProperties":false,"description":"A suppression after a bypass or a withdrawn bypass.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"bypassed":{"type":"boolean"}},"required":["id"],"example":{"id":"44444444-4444-4444-8444-444444444444","bypassed":true}},"EmailCampaignSummary":{"type":"object","additionalProperties":false,"description":"An email campaign without the full HTML body.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","paused","failed","canceled"]},"subject":{"type":"string","nullable":true},"total_recipients":{"type":"integer","minimum":0},"scheduled_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}},"required":["id","name","status"],"example":{"id":"55555555-5555-4555-8555-555555555555","name":"October update","status":"draft"}},"EmailCampaignList":{"type":"object","additionalProperties":false,"description":"Email campaigns for this organization.","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/EmailCampaignSummary"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]},"metricDefinitions":{"type":"object","additionalProperties":{"type":"string"},"description":"Plain-English meaning of each count field."}},"required":["campaigns"],"example":{"campaigns":[]}},"EmailCampaignDetail":{"type":"object","additionalProperties":false,"description":"Stored email content, counts, and schedule.","properties":{"campaign":{"type":"object","additionalProperties":true,"required":["id","name","status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","sending","sent","paused","failed","canceled"]},"subject":{"type":"string","nullable":true},"message_content":{"type":"string","nullable":true},"from_name":{"type":"string","nullable":true},"from_email":{"type":"string","format":"email","nullable":true},"scheduled_at":{"type":"string","format":"date-time","nullable":true},"segmentIds":{"type":"array","items":{"type":"string","format":"uuid"}},"bounced":{"type":"integer","minimum":0},"hard_bounced":{"type":"integer","minimum":0},"soft_bounced":{"type":"integer","minimum":0}}}},"required":["campaign"],"example":{"campaign":{"id":"55555555-5555-4555-8555-555555555555","name":"October update","status":"sent","bounced":2,"hard_bounced":1,"soft_bounced":1}}},"EmailMutation":{"type":"object","additionalProperties":false,"description":"The draft was saved, refreshed, tested, scheduled, or returned to draft.","properties":{"success":{"type":"boolean"},"campaignId":{"type":"string","format":"uuid"},"status":{"type":"string"},"recipientCount":{"type":"integer","minimum":0},"scheduledAt":{"type":"string","format":"date-time","nullable":true}},"required":["success"],"example":{"success":true,"status":"draft"}},"TransactionalEmail":{"type":"object","additionalProperties":false,"description":"One system email. Carrier message ids are not included.","properties":{"id":{"type":"string","format":"uuid"},"subject":{"type":"string","nullable":true},"status":{"type":"string"},"attempt_count":{"type":"integer","minimum":0},"next_attempt_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"charge_cents":{"type":"integer","minimum":0,"description":"Whole cents."}},"required":["id","status"],"example":{"id":"66666666-6666-4666-8666-666666666666","status":"sent","charge_cents":1}},"TransactionalList":{"type":"object","additionalProperties":false,"description":"System emails for this organization.","properties":{"emails":{"type":"array","items":{"$ref":"#/components/schemas/TransactionalEmail"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["emails"],"example":{"emails":[]}},"TransactionalDetail":{"type":"object","additionalProperties":false,"description":"One system email and its recipients. Carrier message ids are omitted.","properties":{"email":{"$ref":"#/components/schemas/TransactionalEmail"},"recipients":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email"},"role":{"type":"string"},"status":{"type":"string"}},"required":["email","status"]}}},"required":["email"],"example":{"email":{"id":"66666666-6666-4666-8666-666666666666","status":"sent"},"recipients":[]}},"TransactionalTemplate":{"type":"object","additionalProperties":false,"description":"A reusable system-email template. Placeholders use double curly braces.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string"},"text":{"type":"string","nullable":true}},"required":["id","name","subject"],"example":{"id":"77777777-7777-4777-8777-777777777777","name":"Receipt","subject":"Your receipt"}},"TransactionalTemplateWrite":{"type":"object","additionalProperties":false,"description":"Create or update a transactional template.","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"subject":{"type":"string","minLength":1,"maxLength":200},"html":{"type":"string","minLength":1},"text":{"type":"string"}},"required":["name","subject","html"],"example":{"name":"Receipt","subject":"Your receipt","html":"<p>Hello {{firstName}}</p>"}},"TemplateList":{"type":"object","additionalProperties":false,"description":"Transactional templates.","properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/TransactionalTemplate"}}},"required":["templates"],"example":{"templates":[]}},"TransactionalWebhookWrite":{"type":"object","additionalProperties":false,"description":"Create a transactional webhook. The url must be https.","properties":{"url":{"type":"string","format":"uri"}},"required":["url"],"example":{"url":"https://example.org/hooks/email"}},"TransactionalWebhookUpdate":{"type":"object","additionalProperties":false,"description":"Turn a transactional webhook on or off.","properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"example":{"enabled":false}},"TransactionalWebhook":{"type":"object","additionalProperties":false,"description":"A transactional webhook endpoint. The secret is omitted.","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}},"required":["id","url","enabled"],"example":{"id":"88888888-8888-4888-8888-888888888888","url":"https://example.org/hooks/email","enabled":true}},"TransactionalWebhookCreated":{"type":"object","additionalProperties":false,"description":"A new transactional webhook. The secret is shown once.","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"secret":{"type":"string"}},"required":["id","url","secret"],"example":{"id":"88888888-8888-4888-8888-888888888888","url":"https://example.org/hooks/email","enabled":true,"secret":"shown-once"}},"TransactionalWebhookList":{"type":"object","additionalProperties":false,"description":"Transactional webhook endpoints for this organization.","properties":{"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/TransactionalWebhook"}}},"required":["endpoints"],"example":{"endpoints":[]}},"TemplateDetail":{"type":"object","additionalProperties":false,"description":"One transactional template.","properties":{"template":{"$ref":"#/components/schemas/TransactionalTemplate"}},"required":["template"],"example":{"template":{"id":"77777777-7777-4777-8777-777777777777","name":"Receipt","subject":"Your receipt"}}},"EmailRecipient":{"type":"object","additionalProperties":false,"description":"One email recipient outcome. Carrier message ids are omitted.","properties":{"id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","format":"uuid","nullable":true},"email":{"type":"string","format":"email"},"status":{"type":"string"},"error":{"type":"string","nullable":true,"description":"Plain language. Carrier text is not passed through."},"sent_at":{"type":"string","format":"date-time","nullable":true},"opened_at":{"type":"string","format":"date-time","nullable":true},"clicked_at":{"type":"string","format":"date-time","nullable":true}},"required":["id","status"],"example":{"id":"88888888-8888-4888-8888-888888888888","email":"voter@example.com","status":"delivered"}},"EmailRecipientPage":{"type":"object","additionalProperties":false,"description":"Paginated email recipient outcomes.","properties":{"recipients":{"type":"array","items":{"$ref":"#/components/schemas/EmailRecipient"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["recipients"],"example":{"recipients":[]}},"EmailEvent":{"type":"object","additionalProperties":false,"description":"One delivery event. Carrier message ids and raw diagnostics are omitted.","properties":{"id":{"type":"string","format":"uuid"},"event_type":{"type":"string","enum":["send","delivery","open","click","bounce","complaint"]},"email_to":{"type":"string","format":"email"},"bounce_type":{"type":"string","nullable":true,"enum":["Permanent","Transient",null]},"created_at":{"type":"string","format":"date-time"}},"required":["id","event_type"],"example":{"id":"99999999-9999-4999-8999-999999999999","event_type":"delivery"}},"EmailEventPage":{"type":"object","additionalProperties":false,"description":"Paginated email delivery events.","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EmailEvent"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["events"],"example":{"events":[]}},"EmailCampaignClicks":{"type":"object","additionalProperties":false,"description":"Opens for one email campaign and clicks grouped by a normalized link or by utm_content.","properties":{"campaignId":{"type":"string","format":"uuid"},"groupBy":{"type":"string","enum":["url","utm_content"],"description":"url is the normalized link. utm_content is that query parameter."},"opens":{"type":"object","additionalProperties":false,"required":["human","appleMpp","machine","raw"],"properties":{"human":{"type":"integer","minimum":0,"description":"Unique recipients whose open is not machine and not Apple MPP. Proxied mail fetches count here. Best estimate of real readers."},"appleMpp":{"type":"integer","minimum":0,"description":"Apple MPP opens. Not included in human or machine."},"machine":{"type":"integer","minimum":0,"description":"Opens stored as machine."},"raw":{"type":"integer","minimum":0,"description":"Unique recipients with any recorded open. Equals the campaign opened_count. Not total open hits."}}},"clicks":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["link","human","raw"],"properties":{"link":{"type":"string","nullable":true,"description":"Normalized URL when groupBy is url. The utm_content value when groupBy is utm_content. Null when the event stored none, or when that click has no utm_content."},"human":{"type":"integer","minimum":0},"raw":{"type":"integer","minimum":0}}}},"definitions":{"type":"object","additionalProperties":true,"description":"Plain-English meaning of each opens and clicks count."}},"required":["campaignId","groupBy","opens","clicks"],"example":{"campaignId":"55555555-5555-4555-8555-555555555555","groupBy":"url","opens":{"human":2,"appleMpp":1,"machine":1,"raw":4},"clicks":[{"link":"https://example.org/vote","human":1,"raw":2}]}},"ConversionSourceList":{"type":"object","additionalProperties":false,"description":"Conversion sources for this organization. The token is not included.","properties":{"sources":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","kind","parser","tokenPrefix","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["donation","signup","rsvp"]},"parser":{"type":"string","enum":["anedot","generic"]},"tokenPrefix":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}},"required":["sources"],"example":{"sources":[]}},"ConversionSourceWrite":{"type":"object","additionalProperties":false,"description":"Create a conversion source. An Anedot source is a donation and needs a signing secret of at least 16 characters.","properties":{"kind":{"type":"string","enum":["donation","signup","rsvp"]},"parser":{"type":"string","enum":["anedot","generic"]},"signingSecret":{"type":"string"}},"required":["kind","parser"],"example":{"kind":"signup","parser":"generic"}},"ConversionSourceCreated":{"type":"object","additionalProperties":false,"description":"The source was created. The token is returned once.","properties":{"source":{"type":"object","additionalProperties":false,"required":["id","kind","parser","token","webhookUrl"],"properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["donation","signup","rsvp"]},"parser":{"type":"string","enum":["anedot","generic"]},"token":{"type":"string"},"webhookUrl":{"type":"string"},"pixelUrl":{"type":"string","nullable":true}}}},"required":["source"],"example":{"source":{"id":"55555555-5555-4555-8555-555555555555","kind":"signup","parser":"generic","token":"token","webhookUrl":"https://example.com/api/webhooks/conversions/token","pixelUrl":"https://example.com/c/token"}}},"CampaignPerformanceReport":{"type":"object","additionalProperties":false,"description":"Human clicks, conversions, and throughput for one campaign. Email, phone, and tokens are omitted.","properties":{"campaignId":{"type":"string","format":"uuid"},"channel":{"type":"string","nullable":true,"enum":["email","sms","mms",null]},"conversions":{"type":"object","additionalProperties":true},"throughput":{"type":"object","additionalProperties":false,"required":["sent","delivered","failed","startedAt","completedAt","perMinute"],"properties":{"sent":{"type":"integer","nullable":true,"minimum":0},"delivered":{"type":"integer","nullable":true,"minimum":0},"failed":{"type":"integer","nullable":true,"minimum":0},"startedAt":{"type":"string","nullable":true,"format":"date-time"},"completedAt":{"type":"string","nullable":true,"format":"date-time"},"perMinute":{"type":"number","nullable":true}}},"clicks":{"type":"array","nullable":true,"items":{"type":"object","additionalProperties":false,"required":["link","human","raw"],"properties":{"link":{"type":"string","nullable":true},"human":{"type":"integer","minimum":0},"raw":{"type":"integer","minimum":0}}}}},"required":["campaignId","channel","conversions","throughput","clicks"],"example":{"campaignId":"55555555-5555-4555-8555-555555555555","channel":"email","conversions":{"total":0,"amountCents":0,"kinds":[],"links":[]},"throughput":{"sent":10,"delivered":9,"failed":1,"startedAt":"2026-10-16T00:00:00.000Z","completedAt":"2026-10-16T00:10:00.000Z","perMinute":1},"clicks":[{"link":"https://example.org/vote","human":1,"raw":2}]}},"ConversionResult":{"type":"object","additionalProperties":false,"description":"The conversion was stored.","properties":{"success":{"type":"boolean","const":true},"id":{"type":"string","format":"uuid"}},"required":["success"],"example":{"success":true}},"VerificationResult":{"type":"object","additionalProperties":false,"description":"A verification quote or a completed check. Balance is whole cents.","properties":{"success":{"type":"boolean"},"costCents":{"type":"integer","minimum":0,"description":"Whole cents."},"uniqueToCheck":{"type":"integer","minimum":0},"balanceCents":{"type":"integer"},"configured":{"type":"boolean"}},"required":["costCents"],"example":{"success":true,"costCents":100,"uniqueToCheck":10,"configured":true}},"SmsReadiness":{"type":"object","additionalProperties":false,"description":"Whether this organization can send texts or pictures.","properties":{"sms":{"type":"object","additionalProperties":false,"required":["ready","blockers"],"properties":{"ready":{"type":"boolean"},"blockers":{"type":"array","items":{"type":"string"}},"sender":{"type":"object","nullable":true,"properties":{"label":{"type":"string","nullable":true},"maskedPhone":{"type":"string"}}}}},"mms":{"type":"object","additionalProperties":false,"required":["ready","blockers"],"properties":{"ready":{"type":"boolean"},"blockers":{"type":"array","items":{"type":"string"}}}}},"required":["sms","mms"],"example":{"sms":{"ready":true,"blockers":[]},"mms":{"ready":false,"blockers":["Picture messaging is not enabled on the sending number."]}}},"SmsPreview":{"type":"object","additionalProperties":false,"description":"Text audience and cost. Nothing is sent or charged.","properties":{"recipientCount":{"type":"integer","minimum":0},"costCents":{"type":"integer","minimum":0,"description":"Whole cents."},"segmentCount":{"type":"integer","minimum":1},"balanceCents":{"type":"integer"}},"required":["recipientCount","costCents"],"example":{"recipientCount":100,"costCents":300,"segmentCount":1}},"SmsMutation":{"type":"object","additionalProperties":false,"description":"A text draft was tested, started, scheduled, or returned to draft.","properties":{"success":{"type":"boolean"},"status":{"type":"string"},"campaignId":{"type":"string","format":"uuid"},"scheduledAt":{"type":"string","format":"date-time","nullable":true}},"required":["success"],"example":{"success":true,"status":"sending"}},"SmsRecipientPage":{"type":"object","additionalProperties":false,"description":"Text recipient outcomes. Full phone numbers are omitted. Error text is plain language.","properties":{"recipients":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","sending","sent","delivered","failed","skipped"]},"error":{"type":"string","nullable":true},"costCents":{"type":"integer","nullable":true}},"required":["id","status"]}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["recipients"],"example":{"recipients":[]}},"SmsEventPage":{"type":"object","additionalProperties":false,"description":"Text delivery events.","properties":{"events":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["events"],"example":{"events":[]}},"SmsCampaignClicks":{"type":"object","additionalProperties":false,"description":"Clicks for each tracked link on one text campaign. Redirect tokens are omitted.","properties":{"campaignId":{"type":"string","format":"uuid"},"clicks":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["linkId","destination","human","raw"],"properties":{"linkId":{"type":"string","description":"Stable id of the https destination."},"destination":{"type":"string","description":"The https destination. An authored http link is stored as https. Tracking parameters are added at redirect time."},"human":{"type":"integer","minimum":0,"description":"Taps that are not a scanner. A second tap counts. Zero when the link has not been opened."},"raw":{"type":"integer","minimum":0,"description":"Every recorded tap, including a scanner and a second tap."}}}}},"required":["campaignId","clicks"],"example":{"campaignId":"55555555-5555-4555-8555-555555555555","clicks":[{"linkId":"abc123","destination":"https://example.org/vote","human":1,"raw":2}]}},"MailPreview":{"type":"object","additionalProperties":false,"description":"Postcard or letter audience and cost. Nothing is printed or reserved.","properties":{"deliverableCount":{"type":"integer","minimum":0},"estimatedCostCents":{"type":"integer","minimum":0,"description":"Whole cents."},"costPerPieceCents":{"type":"integer","minimum":0,"description":"Whole cents."}},"required":["deliverableCount","estimatedCostCents"],"example":{"deliverableCount":500,"estimatedCostCents":59500,"costPerPieceCents":119}},"MailCreateForm":{"type":"object","additionalProperties":false,"description":"Multipart postcard or letter draft. frontCreative is a file.","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"mailType":{"type":"string","enum":["postcard","letter"]},"postcardSize":{"type":"string","enum":["4x6","6x9","6x11"]},"listId":{"type":"string","format":"uuid"},"frontCreative":{"type":"string","format":"binary"},"backCreative":{"type":"string","format":"binary"},"letterCreative":{"type":"string","format":"binary"},"includePartialAddresses":{"type":"string","enum":["true","false"]},"oneMailPerAddress":{"type":"string","enum":["true","false"]},"isTest":{"type":"string","enum":["true","false"],"description":"Hidden. true keeps the campaign out of ordinary lists."}},"required":["name","mailType","frontCreative"],"example":{"name":"Walk card","mailType":"postcard","postcardSize":"4x6"}},"MailCampaign":{"type":"object","additionalProperties":false,"description":"A postcard or letter campaign. Creative file URLs are omitted.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mail_type":{"type":"string","enum":["postcard","letter"]},"postcard_size":{"type":"string","nullable":true,"enum":["4x6","6x9","6x11",null]},"status":{"type":"string","enum":["draft","queued","processing","mailed","paused","completed","failed","canceled","needs_attention"]},"estimated_recipients":{"type":"integer","minimum":0},"cost_per_piece_cents":{"type":"integer","minimum":0,"description":"Whole cents."},"estimated_cost_cents":{"type":"integer","minimum":0,"description":"Whole cents."},"created_at":{"type":"string","format":"date-time"},"is_test":{"type":"boolean","description":"Hidden test campaigns are omitted from ordinary lists. Default false."}},"required":["id","name","mail_type","status"],"example":{"id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","name":"Walk card","mail_type":"postcard","status":"draft","cost_per_piece_cents":119}},"MailList":{"type":"object","additionalProperties":false,"description":"Postcard and letter campaigns.","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/MailCampaign"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["campaigns"],"example":{"campaigns":[]}},"MailDetail":{"type":"object","additionalProperties":false,"description":"Configuration and progress. Recent jobs include why a piece was not sent. Vendor names are removed.","properties":{"campaign":{"$ref":"#/components/schemas/MailCampaign"},"stats":{"type":"object","additionalProperties":true},"recentJobs":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"error_code":{"type":"string","nullable":true,"description":"Why printing failed, without a vendor name. A bare HTTP status is used when that is all the printer returned."},"error_message":{"type":"string","nullable":true,"description":"The printer's reason, with vendor names removed."},"updated_at":{"type":"string","format":"date-time"}},"required":["id","status"]}}},"required":["campaign"],"example":{"campaign":{"id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","name":"Walk card","mail_type":"postcard","status":"draft"},"recentJobs":[]}},"MailLaunch":{"type":"object","additionalProperties":false,"description":"Printing was submitted. It cannot be recalled.","properties":{"success":{"type":"boolean"},"status":{"type":"string"}},"required":["success"],"example":{"success":true,"status":"queued"}},"VoiceNumber":{"type":"object","additionalProperties":false,"description":"An active voice-enabled sending number. The number is masked.","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":"string","nullable":true},"maskedPhone":{"type":"string"},"voiceEnabled":{"type":"boolean"}},"required":["id"],"example":{"id":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","maskedPhone":"(813) ***-1234","voiceEnabled":true}},"VoiceNumberList":{"type":"object","additionalProperties":false,"description":"Voice caller ids for this organization.","properties":{"numbers":{"type":"array","items":{"$ref":"#/components/schemas/VoiceNumber"}}},"required":["numbers"],"example":{"numbers":[]}},"VoiceAssetUpload":{"type":"object","additionalProperties":false,"description":"Multipart voicemail upload. file is MP3 or WAV, at most 10 MB.","properties":{"file":{"type":"string","format":"binary","description":"audio/mpeg or audio/wav"}},"required":["file"],"example":{}},"VoiceCampaignSummary":{"type":"object","additionalProperties":false,"description":"A call or voicemail campaign.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"type":{"type":"string","enum":["call","voicemail","robocall"]},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","type","status"],"example":{"id":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","name":"Saturday calls","type":"call","status":"draft"}},"VoiceCampaignList":{"type":"object","additionalProperties":false,"description":"Call and voicemail campaigns.","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/VoiceCampaignSummary"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["campaigns"],"example":{"campaigns":[]}},"VoiceCampaignDetail":{"type":"object","additionalProperties":false,"description":"One call or voicemail campaign and recipient counts.","properties":{"campaign":{"$ref":"#/components/schemas/VoiceCampaignSummary"},"recipients":{"type":"object","additionalProperties":true}},"required":["campaign"],"example":{"campaign":{"id":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","type":"voicemail","status":"draft"}}},"VoiceLaunchResult":{"type":"object","additionalProperties":false,"description":"Voicemail delivery started.","properties":{"success":{"type":"boolean"},"status":{"type":"string"},"providerSubmitted":{"type":"boolean"}},"required":["success"],"example":{"success":true,"status":"sending","providerSubmitted":true}},"VoiceRecordingTest":{"type":"object","additionalProperties":false,"description":"One recording test was placed to the key owner's registered phone. The list was not dialed.","properties":{"success":{"type":"boolean"},"test":{"type":"boolean"},"personalPhoneTest":{"type":"boolean"},"session":{"$ref":"#/components/schemas/CallSession"},"reused":{"type":"boolean"},"providerSubmitted":{"type":"boolean"}},"required":["success","test","personalPhoneTest"],"example":{"success":true,"test":true,"personalPhoneTest":true,"reused":false,"providerSubmitted":true}},"VoiceRobocallTestRequest":{"type":"object","additionalProperties":false,"description":"An organization-owned recording to play to the key owner's registered phone.","properties":{"audioUrl":{"type":"string","format":"uri"},"audioAssetToken":{"type":"string","description":"Opaque token from the voice asset upload."},"audioDuration":{"type":"integer","minimum":1,"maximum":300},"ccNumberId":{"type":"string"},"approvalId":{"type":"string"}},"required":["audioUrl","audioAssetToken","audioDuration"],"example":{"audioUrl":"https://assets.campaigncommanderapp.com/recordings/deadline.mp3","audioAssetToken":"v2.example","audioDuration":42}},"VoiceRecipientPage":{"type":"object","additionalProperties":false,"description":"Call outcomes. Full phone numbers are omitted.","properties":{"recipients":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["recipients"],"example":{"recipients":[]}},"CallSession":{"type":"object","additionalProperties":false,"description":"A live or finished operator-first call. Browser audio is not part of this API.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"contactName":{"type":"string","nullable":true},"startedAt":{"type":"string","format":"date-time","nullable":true}},"required":["id","status"],"example":{"id":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","status":"in_progress"}},"CallStart":{"type":"object","additionalProperties":false,"description":"The operator leg was dialed, or an existing session was reused.","properties":{"success":{"type":"boolean"},"session":{"$ref":"#/components/schemas/CallSession"},"reused":{"type":"boolean"},"providerSubmitted":{"type":"boolean"}},"required":["success","session"],"example":{"success":true,"session":{"id":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","status":"ringing_agent"},"reused":false,"providerSubmitted":true}},"CallActive":{"type":"object","additionalProperties":false,"description":"The operator's current call, if one is up.","properties":{"session":{"allOf":[{"$ref":"#/components/schemas/CallSession"}],"nullable":true},"activeCall":{"type":"object","nullable":true,"additionalProperties":true}},"required":["session"],"example":{"session":null,"activeCall":null}},"CallControlResult":{"type":"object","additionalProperties":false,"description":"The on-screen control was accepted. Next hangs up the voter only.","properties":{"success":{"type":"boolean"},"session":{"$ref":"#/components/schemas/CallSession"}},"required":["success"],"example":{"success":true}},"MailPreviewRequest":{"type":"object","additionalProperties":false,"description":"Audience and format for a print estimate. Nothing is reserved.","properties":{"mailType":{"type":"string","enum":["postcard","letter"]},"postcardSize":{"type":"string","enum":["4x6","6x9","6x11"]},"recipientType":{"type":"string","enum":["all","segment"]},"segmentId":{"type":"string","format":"uuid"}},"required":["mailType","recipientType"],"example":{"mailType":"postcard","postcardSize":"4x6","recipientType":"all"}},"PowerDialerOpened":{"type":"object","additionalProperties":false,"description":"A dialer session is ready. No voter is dialed until the operator answers.","properties":{"success":{"type":"boolean"},"session":{"type":"object","additionalProperties":true},"reused":{"type":"boolean"},"providerSubmitted":{"type":"boolean"}},"required":["success","session"],"example":{"success":true,"session":{"id":"eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee","status":"ready"},"reused":false,"providerSubmitted":false}},"PowerDialerList":{"type":"object","additionalProperties":false,"description":"Dialer sessions for this key.","properties":{"sessions":{"type":"array","items":{"type":"object","additionalProperties":true}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["sessions"],"example":{"sessions":[]}},"PowerDialerSession":{"type":"object","additionalProperties":false,"description":"One dialer session.","properties":{"session":{"type":"object","additionalProperties":true}},"required":["session"],"example":{"session":{"id":"eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee","status":"ready"}}},"AuditPage":{"type":"object","additionalProperties":false,"description":"This organization's audit log entries, newest first.","properties":{"events":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","format":"uuid"},"action":{"type":"string"},"api_key_id":{"type":["string","null"],"format":"uuid"},"actor_user_id":{"type":["string","null"],"format":"uuid"},"resource_type":{"type":["string","null"]},"resource_id":{"type":["string","null"]},"request_id":{"type":["string","null"]},"source":{"type":["string","null"],"enum":["ui","api","mcp","cron","import","system",null]},"outcome":{"type":["string","null"],"enum":["started","succeeded","partial","failed","blocked",null],"description":"Set on paid and bulk actions. started means no outcome has been recorded yet."},"estimated_cost_cents":{"type":["integer","null"]},"actual_cost_cents":{"type":["integer","null"]},"target_type":{"type":["string","null"]},"target_ids":{"type":["array","null"],"items":{"type":"string"}},"target_names":{"type":["array","null"],"items":{"type":"string"}},"count_requested":{"type":["integer","null"]},"count_processed":{"type":["integer","null"]},"count_succeeded":{"type":["integer","null"]},"count_failed":{"type":["integer","null"]},"started_at":{"type":["string","null"],"format":"date-time"},"finished_at":{"type":["string","null"],"format":"date-time"},"error_message":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"}},"required":["id","action"]}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["events","pagination"],"example":{"events":[],"pagination":{"page":1,"limit":100,"total":0,"hasMore":false}}},"BillingBalance":{"type":"object","additionalProperties":false,"description":"Organization funds. availableBalanceCents is the actual spendable balance with active holds already deducted; outstandingHoldsCents is the total currently reserved and not yet settled or voided. The holds are never subtracted again.","properties":{"organizationId":{"type":"string","format":"uuid"},"balance":{"type":"object","additionalProperties":false,"properties":{"availableBalanceCents":{"type":"integer","description":"Actual spendable balance in whole cents."},"outstandingHoldsCents":{"type":"integer","description":"Total held reservations in whole cents."},"currency":{"type":"string","const":"USD"},"asOf":{"type":"string","format":"date-time"}},"required":["availableBalanceCents","outstandingHoldsCents","currency","asOf"]}},"required":["organizationId","balance"],"example":{"organizationId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","balance":{"availableBalanceCents":12450,"outstandingHoldsCents":4200,"currency":"USD","asOf":"2026-10-12T18:00:00Z"}}},"BillingTransaction":{"type":"object","additionalProperties":false,"description":"One ledger entry. Only the public ledger id, type, amount, running balance, description, and timestamp are returned.","properties":{"id":{"type":"string","format":"uuid"},"transaction_type":{"type":"string"},"amount_cents":{"type":"integer"},"balance_after_cents":{"type":"integer","nullable":true},"description":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}},"required":["id","transaction_type","amount_cents","created_at"],"example":{"id":"33333333-3333-4333-8333-333333333333","transaction_type":"campaign_charge","amount_cents":-300,"balance_after_cents":12150,"description":"SMS campaign","created_at":"2026-10-12T18:00:00Z"}},"BillingTransactionPage":{"type":"object","additionalProperties":false,"description":"A page of ledger entries with an exact total and a has-more flag.","properties":{"organizationId":{"type":"string","format":"uuid"},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/BillingTransaction"}},"pagination":{"type":"object","additionalProperties":false,"properties":{"offset":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["offset","limit","total","hasMore"]}},"required":["organizationId","transactions","pagination"],"example":{"organizationId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","transactions":[],"pagination":{"offset":0,"limit":10,"total":0,"hasMore":false}}},"BillingAutoTopUpConfiguration":{"type":"object","additionalProperties":false,"description":"The saved automatic-replenishment configuration. The saved payment method is reported as brand, last 4 digits, and expiry only, and never a card number or identifier.","properties":{"enabled":{"type":"boolean","description":"When true, future automatic charges are authorized against the saved card."},"thresholdCents":{"type":"integer","minimum":500,"maximum":100000},"amountCents":{"type":"integer","minimum":1000,"maximum":100000},"maxTopUpsPerDay":{"type":"integer"},"maxAmountPerDayCents":{"type":"integer"},"cooldownMinutes":{"type":"integer"},"disabledReason":{"type":"string","nullable":true},"paymentMethod":{"type":"object","nullable":true,"additionalProperties":false,"properties":{"brand":{"type":"string","nullable":true},"last4":{"type":"string","nullable":true},"expMonth":{"type":"integer","nullable":true},"expYear":{"type":"integer","nullable":true}}}},"required":["enabled","thresholdCents","amountCents"],"example":{"enabled":true,"thresholdCents":2500,"amountCents":10000,"paymentMethod":{"brand":"visa","last4":"4242","expMonth":4,"expYear":2028}}},"BillingAutoTopUp":{"type":"object","additionalProperties":false,"description":"This organization's saved Auto Top-Up configuration, or null when none is saved.","properties":{"organizationId":{"type":"string","format":"uuid"},"settings":{"allOf":[{"$ref":"#/components/schemas/BillingAutoTopUpConfiguration"}],"nullable":true}},"required":["organizationId"],"example":{"organizationId":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","settings":null}},"BillingAutoTopUpUpdate":{"type":"object","additionalProperties":false,"description":"A full Auto Top-Up configuration save. Enabling authorizes future automatic charges against the already-saved card; it does not charge now and cannot add or remove a card.","properties":{"enabled":{"type":"boolean"},"thresholdCents":{"type":"integer","minimum":500,"maximum":100000},"amountCents":{"type":"integer","minimum":1000,"maximum":100000}},"required":["enabled","thresholdCents","amountCents"],"example":{"enabled":true,"thresholdCents":2500,"amountCents":10000}},"ContactImportPreviewForm":{"type":"object","additionalProperties":false,"description":"Multipart form for a contact or suppression import preview. The file field repeats for multiple CSV/XLSX workbooks. plan, tags and reviewChoices carry the operator's per-tab decisions, list tags and metadata answers so nothing is dropped.","properties":{"file":{"type":"array","items":{"type":"string","format":"binary"},"description":"One or more CSV or XLSX files."},"plan":{"type":"string","description":"JSON array of per-tab decisions: name, key, role (contacts|suppression|ignore), channels, and column mapping. Omit to accept the automatic classification."},"tags":{"type":"string","description":"Comma-separated tags applied to every imported contact."},"metadataToken":{"type":"string","description":"A prior preview token, to reuse the frozen classification instead of re-running the classifier."},"reviewChoices":{"type":"string","description":"JSON object of metadata answers, keyed '<evidenceId>', each 'suppress' or 'none'."},"cleanEmails":{"type":"boolean","description":"Ask to clean imported emails later. Only enforced at commit."},"cleanAddresses":{"type":"boolean","description":"Ask to clean imported addresses later. Only enforced at commit."},"smsConsentAttested":{"type":"boolean","description":"Operator attests the file carries SMS consent for its phone numbers."},"voiceConsentAttested":{"type":"boolean","description":"Operator attests the file carries voice-call consent for its phone numbers."}},"required":["file"],"example":{"file":["voters.csv"],"tags":"canvass"}},"ContactImportCommitForm":{"type":"object","additionalProperties":false,"description":"Multipart form for committing a previewed import. Send the same files and options as the preview, plus the previewToken. Cleaned emails require email:verify and cleaned addresses require address:verify, refused before any contact write when absent.","properties":{"file":{"type":"array","items":{"type":"string","format":"binary"},"description":"The same CSV/XLSX files that were previewed."},"previewToken":{"type":"string","description":"The signed token returned by the preview."},"plan":{"type":"string","description":"JSON array of per-tab decisions, unchanged from the preview."},"tags":{"type":"string","description":"Comma-separated tags, unchanged from the preview."},"reviewChoices":{"type":"string","description":"JSON metadata answers, unchanged from the preview."},"cleanEmails":{"type":"boolean","description":"Request email cleaning. Scope email:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit."},"cleanAddresses":{"type":"boolean","description":"Request address cleaning. Scope address:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit."},"smsConsentAttested":{"type":"boolean"},"voiceConsentAttested":{"type":"boolean"}},"required":["file","previewToken"],"example":{"file":["voters.csv"],"previewToken":"eyJ...signature","tags":"canvass"}},"ContactImportPreview":{"type":"object","additionalProperties":false,"description":"A parsed, classified import preview. It writes preview evidence only and changes no contacts. Carries the exact counts, unresolved decisions, suppression matches and the signed preview token to commit.","properties":{"sheets":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportSheet"},"description":"Per-tab classification with role, headers, suggested mapping and reasons."},"preview":{"$ref":"#/components/schemas/ContactImportPreviewBody"},"previewToken":{"type":"string","description":"Signed token to commit this exact upload and mapping."},"metadataToken":{"type":"string","description":"Signed token to reuse the frozen classification on a refresh."},"ledgerMatches":{"type":"object","additionalProperties":true,"description":"How many file emails and phones already match this organization's suppression ledger."}},"required":["preview","previewToken"],"example":{"preview":{"totalRows":2,"counts":{"create":2,"merge":0,"skip":0,"suppress":0}},"previewToken":"eyJ...signature"}},"ContactImportPreviewBody":{"type":"object","additionalProperties":false,"description":"The row-by-row body of a preview or a commit. Every row explanation travels as `source_reason` and each before/after source cell value as `source_before`/`source_after`, the import-specific key names that survive redaction. The exact counts and unresolved decision ids pass through.","properties":{"hash":{"type":"string","nullable":true,"description":"The canonical plan hash the commit binds to."},"totalRows":{"type":"integer"},"counts":{"type":"object","additionalProperties":true,"description":"Rows by kind: create, merge, skip, suppress."},"rows":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportOutcome"}},"reasonTotals":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"source_reason":{"type":"string"},"count":{"type":"integer"}}},"description":"Rows by reason; the reason travels as `source_reason` so a reason naming an ordinary organization survives."},"mergeBreakdown":{"type":"object","additionalProperties":true,"nullable":true},"metadata":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Classifier evidence, including unresolved decision ids."},"unresolved":{"type":"array","items":{"type":"string"}},"uniqueContactMutations":{"type":"integer"},"uniqueEmails":{"type":"integer"},"ignoredRows":{"type":"integer"}},"required":["rows","totalRows"],"example":{"totalRows":2,"counts":{"create":2,"merge":0,"skip":0,"suppress":0},"rows":[{"row_number":2,"kind":"create","source_reason":"Create contact"}]}},"ContactImportSheet":{"type":"object","additionalProperties":false,"description":"One classified tab. The tab label, the file's own column headers and the suggested column mapping are the customer's own column names and are exactly what the caller echoes back to build the commit plan, so they travel under import-specific `source_*` names that survive redaction; a generic `headers`/`mapping`/`key` elsewhere is still scrubbed.","properties":{"name":{"type":"string","nullable":true,"description":"The tab label from the uploaded workbook."},"source_key":{"type":"string","nullable":true,"description":"Stable tab key within the upload, to pin the plan."},"file_name":{"type":"string","nullable":true},"role":{"type":"string","enum":["contacts","suppression","ignore"]},"row_count":{"type":"integer"},"source_headers":{"type":"array","items":{"type":"string"},"description":"The file's own column headers, verbatim."},"source_mapping":{"type":"object","additionalProperties":true,"description":"Suggested column header per field, plus a custom header-to-field map."},"source_reasons":{"type":"array","items":{"type":"string"},"description":"Plain-language classification reasons."},"source_samples":{"type":"array","items":{"type":"object","additionalProperties":true}},"default_channels":{"type":"object","additionalProperties":true},"source_status_counts":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["role"],"example":{"name":"Volunteers","source_key":"Volunteers","role":"contacts","source_headers":["Column A","First Name"]}},"ContactImportSheetSummary":{"type":"object","additionalProperties":false,"description":"One per-workbook summary from a completed commit, projected the same way: the summary explanation travels as `source_reason`.","properties":{"name":{"type":"string","nullable":true},"role":{"type":"string","enum":["contacts","suppression","ignore"]},"row_count":{"type":"integer"},"source_reason":{"type":"string","nullable":true}},"required":["role"],"example":{"name":"Volunteers","role":"contacts","row_count":2,"source_reason":"Columns include a name, an email, a phone, or an address."}},"ContactImportCommit":{"type":"object","additionalProperties":false,"description":"The persisted result of committing an import. Nothing is charged and no list cleaning is performed inline; when cleaning was requested the response carries a `cleaning` block reporting the channels as requested and not performed, and cohortId names the separate cohort-scoped paid step. The previewed rows are returned under the same redaction-safe shape as the preview.","properties":{"success":{"type":"boolean"},"imported":{"type":"integer"},"taggedExisting":{"type":"integer"},"skippedDuplicates":{"type":"integer"},"phonesNotUsable":{"type":"integer"},"emailsNotUsable":{"type":"integer"},"rejected":{"type":"integer"},"alreadySuppressed":{"type":"integer"},"replayed":{"type":"boolean","description":"Present and true when an unchanged commit returned the stored receipt."},"jobId":{"type":"string","format":"uuid","nullable":true},"cohortId":{"type":["string","null"],"format":"uuid","description":"The stable id of the frozen import identity cohort captured with a preview-backed commit. Absent for legacy/no-snapshot commits. Its presence means a frozen identity set was saved, not that anything was cleaned or charged."},"jobs":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"One job per workbook."},"list":{"type":"string","nullable":true,"description":"The first list tag applied."},"cleaningError":{"type":"string","nullable":true,"description":"Why optional list cleaning did not complete, when it did not."},"preview":{"$ref":"#/components/schemas/ContactImportPreviewBody"},"sheets":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportSheetSummary"}},"cleaning":{"type":"object","nullable":true,"additionalProperties":true,"description":"Present when cleaning was requested. Lists the requested channels and states that cleaning was NOT performed by this commit, and that it is available as a separate cohort-scoped paid step keyed by cohortId."}},"required":["success","imported"],"example":{"success":true,"imported":2,"skippedDuplicates":0,"cleaningError":null}},"ContactImportHistory":{"type":"object","additionalProperties":false,"description":"Bounded, newest-first history of this organization's imports with an honest continuation.","properties":{"imports":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportHistoryRow"}},"has_more":{"type":"boolean"},"next_offset":{"type":"integer","nullable":true}},"required":["imports","has_more"],"example":{"imports":[],"has_more":false,"next_offset":null}},"ContactImportHistoryRow":{"type":"object","additionalProperties":false,"description":"One persisted import: file name, status, timestamps, counts, suppression counts and evidence version.","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":"string","nullable":true},"status":{"type":"string","nullable":true},"started_at":{"type":"string","format":"date-time"},"finished_at":{"type":"string","format":"date-time","nullable":true},"rows_read":{"type":"integer"},"contacts_created":{"type":"integer"},"contacts_updated":{"type":"integer"},"duplicates_merged":{"type":"integer"},"rows_rejected":{"type":"integer"},"phones_not_usable":{"type":"integer"},"emails_not_usable":{"type":"integer"},"suppressions":{"type":"object","additionalProperties":true,"description":"Suppression counts by channel."},"evidence_version":{"type":"integer"},"outcome_counts":{"type":"object","additionalProperties":true,"nullable":true}},"required":["id"],"example":{"id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","filename":"voters.csv","status":"completed","evidence_version":2}},"ContactImportOutcomes":{"type":"object","additionalProperties":false,"description":"A bounded page of per-row import outcomes with a keyset cursor and an honest continuation. Evidence version 2 reads persisted outcome rows; older jobs fall back to the frozen summary.","properties":{"evidence_version":{"type":"integer"},"outcomes":{"type":"array","items":{"$ref":"#/components/schemas/ContactImportOutcome"}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true},"category":{"type":"string","nullable":true}},"required":["outcomes","has_more"],"example":{"evidence_version":2,"outcomes":[],"has_more":false,"next_cursor":null,"category":null}},"ContactImportOutcome":{"type":"object","additionalProperties":false,"description":"One persisted import outcome row. User-authored values are preserved under import-specific key names (`source_reason`, `source_before`, `source_after`) so a generic `reason` elsewhere is still scrubbed; only the shape is normalized.","properties":{"id":{"type":"string","nullable":true},"sheet_key":{"type":"string","nullable":true},"sheet_name":{"type":"string","nullable":true},"file_name":{"type":"string","nullable":true},"row_number":{"type":"integer","nullable":true},"kind":{"type":"string","enum":["create","merge","suppress","skip"]},"source_reason":{"type":"string","nullable":true,"description":"The customer-authored per-row explanation."},"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"flags":{"type":"array","items":{"type":"string"}},"deltas":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"field":{"type":"string","nullable":true},"source_before":{"nullable":true},"source_after":{"nullable":true}}},"description":"Per-field before/after source cell values, keyed so they survive redaction."}},"required":["kind"],"example":{"id":"42","sheet_name":"Contacts","row_number":2,"kind":"create","source_reason":"Create contact"}},"ContactImportCleaningCohort":{"type":"object","additionalProperties":false,"description":"The safe metadata of one frozen import identity cohort. Captured unique counts only: no raw email/address keys, no billable-unit or pending-check counts, and no cleaning execution status. `paid_cleaning.available` reports that the separate cohort-scoped paid cleaning step exists; it never claims any cleaning has run.","properties":{"cohort":{"type":"object","additionalProperties":false,"properties":{"id":{"type":["string","null"]},"preview_id":{"type":["string","null"]},"import_job_ids":{"type":"array","items":{"type":"string"}},"snapshot_version":{"type":"integer"},"snapshot_fingerprint":{"type":["string","null"]},"requested_channels":{"type":"array","items":{"type":"string"}},"captured_email_count":{"type":"integer"},"captured_address_count":{"type":"integer"},"created_at":{"type":["string","null"]},"capture_state":{"type":"string","enum":["captured"]},"paid_cleaning":{"type":"object","additionalProperties":false,"properties":{"available":{"type":"boolean"},"status":{"type":"string","enum":["available"]}},"required":["available","status"]}},"required":["id","captured_email_count","captured_address_count","capture_state"]}},"required":["cohort"],"example":{"cohort":{"id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","preview_id":"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb","import_job_ids":[],"snapshot_version":1,"snapshot_fingerprint":"0000000000000000000000000000000000000000000000000000000000000000","requested_channels":["email"],"captured_email_count":1,"captured_address_count":0,"created_at":"2026-01-01T00:00:00.000Z","capture_state":"captured","paid_cleaning":{"available":true,"status":"available"}}}},"ContactImportCohortClean":{"type":"object","additionalProperties":false,"description":"The body of a cohort-clean request. It names only channels and an optional approval; the identity set is read from the server-side cohort, never from the caller. Requires confirm true and an idempotency_key because it spends balance.","properties":{"channels":{"type":"array","items":{"type":"string","enum":["email","address"]},"description":"Which identities to clean. At least one."},"confirm":{"type":"boolean","description":"Must be true."},"idempotency_key":{"type":"string","description":"Unique 16 to 128 character key."},"approval_id":{"type":"string","description":"Optional approved operator spend approval id for this exact cohort."}},"required":["channels","confirm","idempotency_key"],"example":{"channels":["email"],"confirm":true,"idempotency_key":"clean-cohort-2026-0001"}},"ContactImportCohortCleanResult":{"type":"object","additionalProperties":false,"description":"The result of cleaning a frozen import identity cohort. Each requested channel reports whether cleaning was requested and performed and its counts. Only the cohort's own identities were checked; no whole-organization run happens. Nothing is charged when no cohort identity needs cleaning.","properties":{"success":{"type":"boolean"},"cohort_id":{"type":"string","format":"uuid"},"chargedCents":{"type":"integer"},"channels":{"type":"object","additionalProperties":true,"description":"Per-channel outcome: requested, performed, counts, and the approved maximum."}},"required":["success","cohort_id","channels"],"example":{"success":true,"cohort_id":"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa","chargedCents":0,"channels":{"email":{"requested":true,"performed":false,"uniqueChecked":0}}}},"ContactImportStagedUpload":{"type":"object","additionalProperties":false,"description":"One chunk of a staged contact-import upload. The first chunk omits staging_id; every later chunk sends the returned id. final true marks the last chunk. Bytes only: nothing is parsed and nothing is charged.","properties":{"filename":{"type":"string","description":"File name for the whole upload."},"content_base64":{"type":"string","description":"This chunk's bytes, base64-encoded."},"staging_id":{"type":"string","description":"The id returned by the first chunk. Omit on the first call."},"final":{"type":"boolean","description":"Set true on the last chunk."}},"required":["filename","content_base64"],"example":{"filename":"voters.csv","content_base64":"RW1haWwKYWRhQGV4YW1wbGUub3JnCg==","final":true}},"ContactImportStagedUploadResult":{"type":"object","additionalProperties":false,"description":"The state of a staged upload after one chunk. The staging_id is the durable reference a later import commit uses for this file. No bytes are echoed.","properties":{"staging_id":{"type":"string","format":"uuid"},"filename":{"type":"string"},"chunk_index":{"type":"integer","description":"0-based index of the chunk just appended."},"bytes_received":{"type":"integer"},"complete":{"type":"boolean"}},"required":["staging_id","chunk_index","bytes_received","complete"],"example":{"staging_id":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","filename":"voters.csv","chunk_index":0,"bytes_received":1048576,"complete":false}},"FormSubmissionChannel":{"type":"object","additionalProperties":false,"description":"A channel verdict for one form submission.","properties":{"permitted":{"type":"boolean"},"reason":{"type":"string","enum":["opted_in","already_permitted","not_opted_in","not_provided","opted_out","suppressed","identifier_differs","do_not_contact"]}},"required":["permitted","reason"]},"FormSubmissionRecord":{"type":"object","additionalProperties":false,"description":"A website form submission. Provide an email, a phone, or both, and a source. A checked opt-in box requires its verbatim consent text. A tenant or user selector is refused, not honored.","properties":{"email":{"type":"string","description":"Email address, stored lowercased."},"phone":{"type":"string","description":"U.S. phone number, stored as E.164."},"firstName":{"type":"string"},"lastName":{"type":"string"},"street":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"postalCode":{"type":"string","description":"Postal-code alias accepted when zip is omitted."},"source":{"type":"string","description":"Short form name such as volunteer, membership, contact, newsletter, or event."},"emailOptIn":{"type":"boolean"},"smsOptIn":{"type":"boolean"},"emailConsentText":{"type":"string","description":"The email checkbox label, verbatim, 3 to 2000 characters."},"smsConsentText":{"type":"string","description":"The text checkbox label, verbatim, 3 to 2000 characters."},"optInIpAddress":{"type":"string"},"optInAttestation":{"type":"boolean"},"locale":{"type":"string"},"submittedAt":{"type":"string","format":"date-time"},"externalId":{"type":"string","description":"Stable id, up to 128 characters. Reusing it replays the FIRST accepted submission instead of writing again; the contact and its receipt commit atomically, so a concurrent duplicate never re-mutates the contact. An interrupted keyed retry is not auto-resent; read the receipt for this externalId first."},"attributes":{"type":"object","additionalProperties":{"type":["string","number","boolean"]},"description":"Up to 40 extra fields as text, number, or boolean values."}},"required":["source"],"example":{"email":"ada@example.org","phone":"863-555-0148","firstName":"Ada","source":"volunteer","emailOptIn":true,"emailConsentText":"Send me email updates from the campaign.","externalId":"volunteer-form-100","attributes":{"shift":"saturday","student":true,"year":2026}}},"FormSubmissionAccepted":{"type":"object","additionalProperties":false,"description":"A successful form-intake receipt.","properties":{"contactId":{"type":"string","format":"uuid"},"result":{"type":"string","enum":["created","updated","duplicate"]},"listTag":{"type":"string","description":"The source-derived list tag applied to the contact."},"email":{"$ref":"#/components/schemas/FormSubmissionChannel"},"sms":{"$ref":"#/components/schemas/FormSubmissionChannel"},"ignored":{"type":"array","items":{"type":"string","enum":["email","phone"]}}},"required":["contactId","result","listTag","email","sms","ignored"]},"FormSubmissionConflict":{"type":"object","additionalProperties":false,"description":"An identity-conflict receipt. The email matched one contact and the phone matched a different contact; neither was changed.","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["identity_conflict"]},"result":{"type":"string","enum":["identity_conflict"]},"emailContactId":{"type":"string","format":"uuid"},"phoneContactId":{"type":"string","format":"uuid"},"externalId":{"type":"string"}},"required":["error","code","result","emailContactId","phoneContactId"]},"FormSubmissionReceipt":{"description":"A stored form-intake receipt: a successful created/updated/duplicate result or an identity-conflict refusal.","anyOf":[{"$ref":"#/components/schemas/FormSubmissionAccepted"},{"$ref":"#/components/schemas/FormSubmissionConflict"}]},"FormSubmissionReceiptRead":{"type":"object","additionalProperties":false,"properties":{"receipt":{"$ref":"#/components/schemas/FormSubmissionReceipt"}},"required":["receipt"]},"TeamMemberList":{"type":"object","additionalProperties":false,"description":"The authorized organization's roster, safely projected. Each member's role and membership status come from THAT organization's canonical membership, so a member whose own selected organization is elsewhere is still shown with this organization's role. total is the true number of distinct members, not one page's length; hasMore is computed from the rows actually returned.","properties":{"members":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"full_name":{"type":["string","null"]},"role":{"type":["string","null"]},"membership_status":{"type":["string","null"]},"joined_at":{"type":["string","null"],"description":"Membership join time where the schema supports it."},"created_at":{"type":["string","null"]},"last_activity_at":{"type":["string","null"]},"is_owner":{"type":"boolean","description":"True for the protected organization owner."}},"required":["id","email","full_name","role","membership_status","joined_at","created_at","last_activity_at","is_owner"]}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["members","pagination"],"example":{"members":[{"id":"11111111-1111-4111-8111-111111111111","email":"owner@example.org","full_name":"Ada Owner","role":"owner","membership_status":"active","joined_at":"2026-01-01T00:00:00.000Z","created_at":"2026-01-01T00:00:00.000Z","last_activity_at":null,"is_owner":true}],"pagination":{"page":1,"limit":50,"total":1,"hasMore":false}}},"TeamInvitationList":{"type":"object","additionalProperties":false,"description":"The authorized organization's CURRENT pending invitations. Excludes accepted, cancelled, dismissed, and expired invitations. Never includes an invitation token or copy-link value. total is the true count, not one page's length.","properties":{"invitations":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"role":{"type":["string","null"]},"created_at":{"type":["string","null"]},"expires_at":{"type":["string","null"]}},"required":["id","email","role","created_at","expires_at"]}},"pagination":{"type":"object","additionalProperties":false,"properties":{"page":{"type":"integer","minimum":1},"limit":{"type":"integer","minimum":1},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"}},"required":["page","limit","total","hasMore"]}},"required":["invitations","pagination"],"example":{"invitations":[{"id":"22222222-2222-4222-8222-222222222222","email":"invitee@example.org","role":"admin","created_at":"2026-10-01T00:00:00.000Z","expires_at":"2026-10-08T00:00:00.000Z"}],"pagination":{"page":1,"limit":50,"total":1,"hasMore":false}}},"ContactFieldList":{"type":"object","additionalProperties":false,"description":"The authorized organization's contact-field registry: explicit key/label/type definitions unioned with the keys that already appear in contacts' stored custom values, whose type is inferred from those values. key is preserved verbatim (including spaces and case); label is as stored. This is a bounded, read-only result returning the full registry and total count, not a single page, and it never returns contact values, contact ids, or the contacts that carry a field.","properties":{"fields":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"key":{"type":"string","description":"Field key, preserved verbatim, including spaces and case."},"label":{"type":"string"},"type":{"type":"string","enum":["text","number","date","boolean"]}},"required":["key","label","type"]}},"total":{"type":"integer","minimum":0,"description":"The true number of discovered fields."}},"required":["fields","total"],"example":{"fields":[{"key":"precinct","label":"Precinct","type":"number"},{"key":"VoterID","label":"VoterID","type":"text"}],"total":2}},"ContactFieldWriteRequest":{"type":"object","additionalProperties":false,"description":"One explicit contact-field definition to upsert, keyed by key. A caller-supplied tenant/provider/actor selector is refused, not stripped. This saves field METADATA only: it does not convert, clear, or repair any contact's stored value, and it does not change a stored value's type.","properties":{"key":{"type":"string","minLength":1,"maxLength":120,"description":"Field key, preserved verbatim. At most 120 characters."},"label":{"type":"string","minLength":1,"maxLength":120,"description":"Human-readable label, stored trimmed. At most 120 characters."},"type":{"type":"string","enum":["text","number","date","boolean"]}},"required":["key","label","type"],"example":{"key":"precinct","label":"Precinct","type":"number"}},"ContactFieldWrite":{"type":"object","additionalProperties":false,"description":"The result of saving a contact-field definition. When confirmed is true, field is the ACTUAL stored row read back after the upsert. When confirmed is false the save committed but the stored row could not be read back; the definition was written, so do not treat it as a refusal and do not replay it blindly.","properties":{"success":{"type":"boolean","const":true},"confirmed":{"type":"boolean","description":"True when the stored row was read back after the save."},"field":{"type":"object","additionalProperties":false,"properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string","enum":["text","number","date","boolean"]}},"required":["key","label","type"]}},"required":["success","confirmed"],"example":{"success":true,"confirmed":true,"field":{"key":"precinct","label":"Precinct","type":"number"}}},"SendingDomainDnsRecord":{"type":"object","additionalProperties":false,"description":"One required DNS record to publish for the organization's owned sending domain. The host is the absolute owner name without a final dot; the data is the absolute target.","properties":{"type":{"type":"string","enum":["CNAME"]},"host":{"type":"string"},"relativeHost":{"type":"string"},"data":{"type":"string"},"required":{"type":"boolean","enum":[true]},"purpose":{"type":"string","enum":["dkim"]},"validation":{"type":"string","enum":["identity_verified","not_confirmed"]}},"required":["type","host","relativeHost","data","required","purpose","validation"],"example":{"type":"CNAME","host":"abc._domainkey.example.com","relativeHost":"abc._domainkey","data":"abc.signing-zone.example","required":true,"purpose":"dkim","validation":"not_confirmed"}},"SendingDomainRecommendation":{"type":"object","additionalProperties":false,"description":"An advisory TXT record suggesting SPF or DMARC, offered with a transactional domain. It is not required and is not a proven current DNS state.","properties":{"type":{"type":"string","enum":["TXT"]},"host":{"type":"string"},"relativeHost":{"type":"string"},"data":{"type":"string"},"required":{"type":"boolean","enum":[false]},"purpose":{"type":"string","enum":["spf","dmarc"]},"validation":{"type":"string","enum":["not_checked"]}},"required":["type","host","relativeHost","data","required","purpose","validation"],"example":{"type":"TXT","host":"_dmarc.example.com","relativeHost":"_dmarc","data":"v=DMARC1; p=none","required":false,"purpose":"dmarc","validation":"not_checked"}},"SendingDomainView":{"type":"object","additionalProperties":false,"description":"The organization's sending-domain authentication state and the exact records it must publish. An authenticated domain is never channel-ready, and MAIL FROM is outside this workflow.","properties":{"domain":{"type":["string","null"]},"fromEmail":{"type":["string","null"]},"ownership":{"type":"string","enum":["owned","not_linked","conflict"]},"authenticated":{"type":"boolean"},"status":{"type":"string","enum":["authenticated","awaiting_dns","not_started","not_linked","unavailable","unknown","not_configured"]},"operationComplete":{"type":"boolean"},"providerOutcome":{"type":"string","enum":["not_called","observed","unknown"]},"persistence":{"type":"string","enum":["unchanged","committed","failed","unknown"]},"observation":{"type":"object","additionalProperties":false,"description":"Where the current state was read from and whether it is stale.","properties":{"source":{"type":"string","enum":["provider_readback","stored_snapshot","none"]},"checkedAt":{"type":["string","null"],"format":"date-time"},"stale":{"type":"boolean"}},"required":["source","checkedAt","stale"],"example":{"source":"provider_readback","checkedAt":"2026-10-14T12:00:00.000Z","stale":false}},"dns":{"type":"array","items":{"$ref":"#/components/schemas/SendingDomainDnsRecord"}},"recommendations":{"type":"array","items":{"$ref":"#/components/schemas/SendingDomainRecommendation"}},"channelReadiness":{"type":"object","additionalProperties":false,"description":"Domain authentication is not channel readiness.","properties":{"status":{"type":"string","enum":["not_assessed"]},"domainOnly":{"type":"boolean","enum":[true]}},"required":["status","domainOnly"],"example":{"status":"not_assessed","domainOnly":true}},"mailFrom":{"type":"object","additionalProperties":false,"description":"Custom MAIL FROM is not managed by this workflow.","properties":{"managedByThisWorkflow":{"type":"boolean","enum":[false]},"status":{"type":"string","enum":["not_assessed"]}},"required":["managedByThisWorkflow","status"],"example":{"managedByThisWorkflow":false,"status":"not_assessed"}},"nextAction":{"type":"string","enum":["publish_dns","verify","recover","update_organization_settings","resolve_ownership","none"]},"message":{"type":["string","null"]}},"required":["domain","fromEmail","ownership","authenticated","status","operationComplete","providerOutcome","persistence","observation","dns","recommendations","channelReadiness","mailFrom","nextAction","message"],"example":{"domain":"example.com","fromEmail":"chair@example.com","ownership":"owned","authenticated":false,"status":"awaiting_dns","operationComplete":false,"providerOutcome":"observed","persistence":"unchanged","observation":{"source":"provider_readback","checkedAt":"2026-10-14T12:00:00.000Z","stale":false},"dns":[{"type":"CNAME","host":"abc._domainkey.example.com","relativeHost":"abc._domainkey","data":"abc.signing-zone.example","required":true,"purpose":"dkim","validation":"not_confirmed"}],"recommendations":[],"channelReadiness":{"status":"not_assessed","domainOnly":true},"mailFrom":{"managedByThisWorkflow":false,"status":"not_assessed"},"nextAction":"publish_dns","message":null}},"SendingDomainPreview":{"type":"object","additionalProperties":false,"description":"The result of previewing a sending-domain action. No claim, provider call, or persistence happened.","properties":{"domain":{"type":["string","null"]},"fromEmail":{"type":["string","null"]},"profile":{"type":"string","enum":["campaign","transactional","registry"]},"eligible":{"type":"boolean"},"blockers":{"type":"array","items":{"type":"string"}},"sideEffects":{"type":"array","items":{"type":"string"}}},"required":["domain","fromEmail","profile","eligible","blockers","sideEffects"],"example":{"domain":"example.com","fromEmail":"chair@example.com","profile":"campaign","eligible":true,"blockers":[],"sideEffects":["domain_identity_configuration","domain_configuration_persistence"]}},"SendingDomainPreviewRequest":{"type":"object","additionalProperties":false,"description":"A proposed sending-domain configuration to check. It takes no organization or user selector, no raw records, no URL, and no local path.","properties":{"domain":{"type":"string"},"from_email":{"type":"string"},"profile":{"type":"string","enum":["campaign","transactional","registry"]}},"required":[],"example":{"domain":"example.com","from_email":"chair@example.com","profile":"campaign"}},"SendingDomainConfigureRequest":{"type":"object","additionalProperties":false,"description":"A sending-domain configuration action. It takes no confirmation flag, no organization or user selector, no raw records, no URL, and no local path. action is required.","properties":{"action":{"type":"string","enum":["ensure","verify","recover"]},"profile":{"type":"string","enum":["campaign","transactional","registry"]},"domain":{"type":"string"},"from_email":{"type":"string"}},"required":["action"],"example":{"action":"ensure","profile":"campaign","from_email":"chair@example.com"}},"TestRecipientWrite":{"type":"object","additionalProperties":false,"description":"An address to allow for email test sends after it confirms.","properties":{"email":{"type":"string","format":"email"}},"required":["email"],"example":{"email":"ada@example.org"}},"TestRecipientList":{"type":"object","additionalProperties":false,"description":"Test recipients for this organization. Confirmation links are not included.","properties":{"recipients":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","email","status","createdAt","updatedAt","verifiedAt","verificationSentAt"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending","verified"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"verifiedAt":{"type":"string","format":"date-time","nullable":true},"verificationSentAt":{"type":"string","format":"date-time","nullable":true}}}}},"required":["recipients"],"example":{"recipients":[{"id":"33333333-3333-4333-8333-333333333333","email":"ada@example.org","status":"pending","createdAt":"2026-10-15T04:00:00.000Z","updatedAt":"2026-10-15T04:00:00.000Z","verifiedAt":null,"verificationSentAt":"2026-10-15T04:00:00.000Z"}]}},"TestRecipientEnvelope":{"type":"object","additionalProperties":false,"description":"The saved test recipient, and whether a verification email was sent.","properties":{"recipient":{"type":"object","additionalProperties":false,"required":["id","email","status","createdAt","updatedAt","verifiedAt","verificationSentAt"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending","verified"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"verifiedAt":{"type":"string","format":"date-time","nullable":true},"verificationSentAt":{"type":"string","format":"date-time","nullable":true}}},"verificationEmailSent":{"type":"boolean"},"message":{"type":"string"}},"required":["recipient","verificationEmailSent"],"example":{"recipient":{"id":"33333333-3333-4333-8333-333333333333","email":"ada@example.org","status":"pending","createdAt":"2026-10-15T04:00:00.000Z","updatedAt":"2026-10-15T04:00:00.000Z","verifiedAt":null,"verificationSentAt":"2026-10-15T04:00:00.000Z"},"verificationEmailSent":true}}}},"paths":{"/agent/capabilities":{"get":{"operationId":"getAgentCapabilities","summary":"Read scopes, endpoints, and prices for this key","description":"Use this first. Returns only what this key is allowed to do, plus customer prices. Paid actions run directly when the key has the scope. Legacy spend approvals are optional. Ask the account owner before spending or sending unless they already said to.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Capabilities"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agent/openapi":{"get":{"operationId":"getAgentOpenApiDocument","summary":"Read the public API document","description":"Same JSON as https://www.campaigncommanderapp.com/openapi.json. No API key is required.","tags":["agent"],"security":[],"x-required-scopes":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenApiDocument"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agent/runs":{"get":{"operationId":"listAgentRuns","summary":"List this key's work runs","description":"Owner-visible runs started by this key. Scope agent:runs.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":["agent:runs"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createAgentRun","summary":"Start a work run","description":"Records an objective the account owner can see. Does not send or spend by itself. Scope agent:runs.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":["agent:runs"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunCreate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRun"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agent/runs/{id}":{"get":{"operationId":"getAgentRun","summary":"Read one work run","description":"Only a run created by this key. Scope agent:runs.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":["agent:runs"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRun"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateAgentRun","summary":"Update a work run","description":"Set status or a short progress summary. Scope agent:runs.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":["agent:runs"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRun"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agent/approvals":{"get":{"operationId":"listSpendApprovals","summary":"List legacy spend approvals for this key","description":"Optional. Paid actions do not wait on an approval. Use this only when the caller supplied an approval id.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"requestSpendApproval","summary":"Request an optional legacy spend approval","description":"Optional. Omit this and call the send or schedule route directly when the key has the spend scope. If this key has both a per-run limit and a daily limit, a request within both is approved in this response and approved_by is standing limit. The key id is api_key_id. A request over either limit stays pending. Limits do not grant scopes. A supplied approval id must match a valid single-use approval for this key.","tags":["agent"],"security":[{"bearerAuth":[]}],"x-required-scopes":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Approval"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/communications/settings":{"get":{"operationId":"getCommunicationSettings","summary":"Read sender and compliance settings","description":"From name, from address, reply-to, the public compliance block, and the sending domain's authentication state with the exact DNS records it requires. Domain status and records are read from the provider for an owned domain and are reported not linked otherwise. Scope settings:read.","tags":["communications"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunicationSettings"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/communications/sending-domain":{"get":{"operationId":"getSendingDomain","summary":"Read the sending domain and its DNS records","description":"The credential organization's owned sending-domain state and the exact CNAME records to publish, read from the provider for an owned domain. profile defaults to campaign; campaign and transactional may infer the saved domain, registry requires an explicit domain. A domain this organization does not own is reported not linked without asking the provider, so no other organization's domain is disclosed. Read-only. Scope settings:read.","tags":["communications"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:read"],"parameters":[{"name":"domain","in":"query","required":false,"schema":{"type":"string"},"description":"A sending domain to read. Registry profile requires it."},{"name":"profile","in":"query","required":false,"schema":{"type":"string","enum":["campaign","transactional","registry"]},"description":"Which saved domain profile to read. Defaults to campaign."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainView"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"configureSendingDomain","summary":"Authenticate a sending domain","description":"ensure creates the domain identity and returns the records to publish, verify rechecks an existing identity, and recover resumes a partially completed configuration. Only an active owner or admin in the credential's organization may run it, and it works during an incomplete setup so an owner can finish the From domain. It never sends, charges, turns on a channel, or changes a price, rate, pause, or account state. No confirmation flag is required. It takes no organization or user selector, no raw records, no URL, and no local path. Scope settings:write.","tags":["communications"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainConfigureRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainView"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/communications/sending-domain/preview":{"post":{"operationId":"previewSendingDomain","summary":"Preview a sending-domain action","description":"Reports the proposed domain, whether an ensure, verify, or recover action would be eligible, the blockers, and its side effects. It claims nothing, calls no provider, and saves nothing, and it never inspects an unattached provider identity. It takes no organization or user selector, no raw records, no URL, and no local path. Scope settings:read.","tags":["communications"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainPreviewRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendingDomainPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/organization/settings":{"get":{"operationId":"getOrganizationSettings","summary":"Read organization settings","description":"Committee name, paid-for-by line, mailing address, From name and address, Reply-To, entity type, EIN, legal name, website, and setup completion with the exact missing fields. Verification tokens and provider identifiers are never returned. Scope settings:read.","tags":["organization"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettings"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"updateOrganizationSettings","summary":"Save organization settings","description":"Owner or admin only. Replaces the whole settings form; send the same required fields as Account, Organization settings. Omitted street2, optional contact, EIN, and default phone are cleared; the legal name defaults to the committee name and the website falls back to the optional contact. A saved token mask leaves the stored verification token unchanged. Does not send, register, or charge. Scope settings:write.","tags":["organization"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettingsUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettingsSave"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/profile":{"get":{"operationId":"getPersonalSettings","summary":"Read your own personal profile and preferences","description":"Reads the credential owner's OWN personal profile and preferences: full name, personal phone with its normalized readback, time zone, country, default sender name and addresses, SMS signature, quiet hours, opt-in preferences, and notification preferences. The effect is user-wide: these settings belong to the person across every organization they belong to, not to one organization. Only the owner's own row is returned; roles, administrator flags, balances, credentials, and secrets never are. Scope profile:read.","tags":["profile"],"security":[{"bearerAuth":[]}],"x-required-scopes":["profile:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalSettings"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updatePersonalSettings","summary":"Save your own personal profile and preferences","description":"Owner or admin only. Changes the credential owner's OWN personal profile and preferences (user-wide across every organization they belong to). Only the fields you pass are changed; an omitted field keeps its stored value and an empty string or null clears a string field. A saved phone is normalized but NOT verified, provisioned, or rung. Notification preferences govern future alerts only: saving them does not send, schedule, or charge, and the low-balance threshold is an alert threshold, not a spending limit. It cannot change email/login identity, password, MFA, verification flags, role, membership, organization selection, administrator flags, balance, spending authorization, or API credentials. Scope profile:write.","tags":["profile"],"security":[{"bearerAuth":[]}],"x-required-scopes":["profile:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalSettingsUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalSettingsSave"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intake/form-submissions":{"post":{"operationId":"recordFormSubmission","summary":"Record a website form submission as a contact","description":"The versioned equivalent of the legacy website endpoint POST /api/intake/form-submission, using the SAME parser and consent/suppression engine. Creates or updates one contact inside the credential's organization; sends nothing and charges nothing. Provide an email, a phone, or both, and a source. A checked opt-in box needs its verbatim consent text; an unchecked box withholds that channel. A dated opt-out, a STOP, or a live suppression is never cleared. A body that names a tenant or user selector (organizationId/orgId/org_id/userId/user_id) is refused, not stripped. The contact and its receipt commit in ONE serialized transaction: returns 201 created, 200 updated, or 200 duplicate when the same externalId was already accepted, where a duplicate replays the FIRST accepted receipt without a second mutation. A stored receipt is the historical outcome of the first write, not proof the contact still matches the request (later legitimate edits can change it); a receipt written before the atomic cutover may reflect the old two-step path, and an interrupted keyed retry is not auto-resent; read the receipt first. When an existing email contact and an existing phone contact are two different people, returns 409 identity_conflict with neither contact changed. Scope intake:write.","tags":["intake"],"security":[{"bearerAuth":[]}],"x-required-scopes":["intake:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionRecord"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionReceipt"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intake/form-submissions/{externalId}":{"get":{"operationId":"getFormSubmission","summary":"Read a stored form-submission receipt","description":"Read the persisted receipt of a past submission by the externalId it was sent with, inside the credential's organization; the id is organization-scoped and never selects an organization. Returns a created/updated/duplicate receipt, or an identity_conflict receipt naming both contacts that were left unchanged. A missing receipt is 404; absence does NOT prove that no write occurred, because the contact can be written before its receipt is saved. The receipt is the historical outcome of the first accepted write, not proof that the current contact matches the request. A read failure is an error, never a synthesized success. Read-only; changes nothing. Scope intake:write.","tags":["intake"],"security":[{"bearerAuth":[]}],"x-required-scopes":["intake:write"],"parameters":[{"name":"externalId","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128},"description":"The external id of a past form submission, organization-scoped."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormSubmissionReceiptRead"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/calling/campaigns":{"get":{"operationId":"listMyCallingCampaigns","summary":"List the calling queues you may work","description":"Scope calls:read. Returns the credential organization's prepared calling campaigns with a pending queue, plus this member's OWN active or paused shift session id per queue. The campaign list is organization-wide, not an individual assignment, and only the shift session id is personal. A pending_count of null means the count could not be read (unavailable), not zero, truncated reports whether more campaigns could exist than were read, and shiftsTruncated reports whether this member's own shift page was capped (so a null session_id is not proof of no open shift). It reads no balance, sender identity, contact or audience inventory, and changes no business state (the read records one routine audit row). Member calling-workspace connection.","tags":["calling"],"security":[{"bearerAuth":[]}],"x-required-scopes":["calls:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallingQueues"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/calling/phone":{"patch":{"operationId":"updateMyCallingPhone","summary":"Save your own operator phone","description":"Scope calls:operate. Saves the credential owner's OWN operator phone. The body carries only phone; a caller-supplied user or organization selector is refused, and an unknown field is rejected. The number is normalized but is NOT verified, provisioned, or rung, and this places no call and moves no money. It returns only whether a phone was set and its last four digits. Member calling-workspace connection.","tags":["calling"],"security":[{"bearerAuth":[]}],"x-required-scopes":["calls:operate"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallingPhoneUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallingPhone"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/members":{"get":{"operationId":"listTeamMembers","summary":"List the authorized organization's team roster","description":"Scope team:read. Owner/admin only, on an ACTIVE credential membership (a read-only organization state such as a locked organization stays readable; a suspended or removed membership does not). The organization is the one that owns the credential, never a request selector. Authorization is canonical: each member's role and status come from that organization's membership row, not from the member's own selected organization, and a removed canonical member is not restored from a stale profile pointer. The projection is narrow (member id, email, display name, canonical role/status, membership timestamps, protected-owner flag): no balances, no platform-admin flags, no secrets, no other organization's membership. Bounded page with page/limit; total is the true number of members, not one page's length. Read-only: records one routine audit row and changes no business state. Inviting, re-queuing, or cancelling an invitation and changing, suspending, reactivating, or removing an ordinary member are the separate team:manage operations.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/invitations":{"get":{"operationId":"listTeamInvitations","summary":"List the authorized organization's current pending invitations","description":"Scope team:read. Same canonical owner/admin authentication and ACTIVE-membership requirement as the roster. Returns only the CURRENT pending invitations (this organization, not accepted, not cancelled, not dismissed, not expired), newest first, with id, email, role, created_at and expires_at. It never returns an invitation token or copy-link value, never the history of past or accepted invitations, and sends or resends nothing. Bounded page with page/limit; total is the true count. Read-only: records one routine audit row and changes no business state.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTeamInvitation","summary":"Invite a person to the organization","description":"Invites one person to the credential's organization as admin, member, or volunteer, using the same invitation workflow the dashboard uses. The acting organization and inviter come only from the credential; the body accepts only email and role. A person who already has a membership of any status is refused (reactivate instead); a live pending invitation returns a conflict. The response exposes only safe invitation metadata and a `queued` acknowledgment indicating a source email event was written, NOT proof of delivery. Creates no organization, grants no role, moves no money, returns no invite token. Ordinary owner/admin authority; platform superuser alone is not authority. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationCreate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/fields":{"get":{"operationId":"listContactFields","summary":"List the authorized organization's contact-field registry","description":"Scope contacts:read. Returns the fields that have an explicit key/label/type definition unioned with the keys that already appear in contacts' stored custom values, whose type is inferred from those values. The organization is the one that owns the credential, never a request selector. Each field is key (verbatim, including spaces and case), label and type; the response carries no contact values, contact ids, or contacts. This is a bounded, read-only result returning the full registry and total count, not a single page. Read-only: records one routine API audit row and changes no business state. It does not define, convert, or remove any field.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFieldList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"upsertContactField","summary":"Save one contact-field definition","description":"Scope contacts:write. Upserts one explicit key/label/type definition keyed by the field key. The key is preserved verbatim; the label is stored trimmed; the stored row is read back and returned in field. This is a metadata save only: it does NOT convert, clear, or repair any contact's existing value, and it does NOT change a stored value's type; a value that no longer matches the new type keeps its stored text and the app reports a type change when a filter no longer matches. A repeated identical save settles the row on that key/label/type; it spends nothing and sends nothing. A body that names a tenant or user selector is refused, not stripped. When the save committed but the stored row could not be read back, confirmed is false; that is not a refusal, and it must not be replayed blindly.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFieldWriteRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactFieldWrite"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists":{"get":{"operationId":"listLists","summary":"List saved audiences","description":"Saved lists for this organization. Scope lists:read.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCollection"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createList","summary":"Create a saved list","description":"Name is required. Filters use the same fields as the product. Scope lists:write.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRecord"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists/{id}":{"get":{"operationId":"getList","summary":"Read one saved list","description":"Scope lists:read.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRecord"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateList","summary":"Edit a saved list","description":"Name, description, or filters. Scope lists:write.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRecord"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteList","summary":"Delete a saved list","description":"Refuses a locked list or one still in use. Scope lists:write.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists/{id}/members":{"post":{"operationId":"addListMembers","summary":"Add contacts to a static list","description":"Up to 100 contact ids. Only static tag lists. Scope lists:write.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberIds"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberChange"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeListMembers","summary":"Remove contacts from a static list","description":"Up to 100 contact ids. Scope lists:write.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberIds"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberChange"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists/{id}/usage":{"get":{"operationId":"getListUsage","summary":"Count campaigns that use a list","description":"How many email, text, mail, and calling campaigns reference this list. Scope lists:read.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUsage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists/resolve":{"get":{"operationId":"resolveList","summary":"Resolve an audience from plain language","description":"Returns one list or candidates to confirm. Scope lists:read.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:read"],"parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string"},"description":"Audience description in plain language."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResolve"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/lists/preview":{"post":{"operationId":"previewList","summary":"Count a prospective list","description":"Returns a count, not the contacts. Scope lists:read.","tags":["lists"],"security":[{"bearerAuth":[]}],"x-required-scopes":["lists:read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPreview"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCount"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts":{"get":{"operationId":"listContacts","summary":"Search contacts","description":"Search or list contacts, or look up one contact by exact email or phone. Scope contacts:read. In list mode q, tag, page, limit, sortBy, sortOrder, and filterType apply; sortBy/sortOrder order the page and filterType keeps only contacts whose named field is not NULL (not a claim of deliverability or verification, and a blank value still counts). An exact email or phone does not apply the list options and returns one contact, but supplied enum selectors are still validated. Omit selectors for defaults; explicit empty selectors are invalid. The pagination total and hasMore are null when the database did not return an exact count; unknown is not an end-of-list assertion. Each contact includes its mailing address (address, city, state, zip); address verification internals are never returned.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":25},"description":"Page size. At most 50."},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":100},"description":"Search name, email, or phone."},{"name":"email","in":"query","required":false,"schema":{"type":"string"},"description":"Exact email address. Returns one contact; an exact lookup ignores q, tag, page, limit, sortBy, sortOrder, and filterType."},{"name":"phone","in":"query","required":false,"schema":{"type":"string"},"description":"Exact U.S. phone number, normalized to E.164. Returns one contact; an exact lookup ignores q, tag, page, limit, sortBy, sortOrder, and filterType."},{"name":"tag","in":"query","required":false,"schema":{"type":"string"},"description":"Only contacts that carry this tag."},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","enum":["created_at","first_name","last_name","email","phone"],"default":"created_at"},"description":"Sort field for the paginated list. Ignored in exact email/phone mode."},{"name":"sortOrder","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"description":"Sort direction for the paginated list. Ignored in exact email/phone mode."},{"name":"filterType","in":"query","required":false,"schema":{"type":"string","enum":["all","email","phone","address"],"default":"all"},"description":"Keep only contacts whose named field is present (not NULL). all applies no filter. Ignored in exact email/phone mode."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSearchResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createContact","summary":"Create a contact","description":"Provide at least a name, email, phone, or mailing-address field. A duplicate email returns 409 with the existing contact. A suppressed email returns 409 unless overrideSuppression is true and overrideNote is at least 3 characters. Consent blocks cannot be bypassed. Mailing-address fields are address, city, state, and zip only; verification fields are refused. Scope contacts:write.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/{id}":{"get":{"operationId":"getContact","summary":"Read one contact","description":"Scope contacts:read. Includes the mailing address (address, city, state, zip) and never the address verification internals.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateContact","summary":"Update a contact","description":"Name, email, phone, notes, tags, mailing address, or custom fields. Scope contacts:write. Only the fields you send are changed; a changed mailing address invalidates any prior verification and is fenced on the row version, so a concurrent address edit returns 409 rather than storing a stale address hash.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/{id}/tags":{"post":{"operationId":"addContactTags","summary":"Add tags to a contact","description":"Scope contacts:write.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeContactTags","summary":"Remove tags from a contact","description":"Scope contacts:write.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/{id}/consent":{"patch":{"operationId":"updateContactConsent","summary":"Set channel consent","description":"Set email opt-out, text opt-out, or do-not-contact. Clearing do-not-contact is refused. Scope contacts:write.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsentWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/import/preview":{"post":{"operationId":"previewContactImport","summary":"Preview a contact or suppression import","description":"Multipart form with one or more CSV/XLSX files. Parses the files, classifies the tabs, matches this organization's suppression ledger and returns the exact counts, unresolved metadata decisions and a signed previewToken to commit. Scope contacts:read. It writes preview evidence only, changes no contacts, and charges nothing. Pass plan, tags and reviewChoices to carry the operator's per-tab decisions; pass metadataToken to reuse a frozen classification.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ContactImportPreviewForm"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/import":{"post":{"operationId":"commitContactImport","summary":"Commit a previewed import","description":"Multipart form with the same files and options as the preview plus previewToken. Scope contacts:write; cleaned emails additionally require email:verify and cleaned addresses require address:verify, refused before any contact write when absent. The commit saves contacts and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a SEPARATE paid step, cleanImportCohort, keyed by the cohortId the response carries. The response reports requested cleaning as requested and not performed by this commit. Re-sending an unchanged commit with the same previewToken replays the stored receipt without importing twice.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write","email:verify","address:verify"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ContactImportCommitForm"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportCommit"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/imports":{"get":{"operationId":"listContactImports","summary":"List this organization's imports","description":"Newest first, bounded page with an honest continuation. Returns counts per import only, never per-row outcomes. Scope contacts:read. A missing migration is reported as an error, not an empty list.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":1000000,"default":0},"description":"How many newest entries to skip."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportHistory"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/imports/{id}/outcomes":{"get":{"operationId":"getContactImportOutcomes","summary":"Read per-row import outcomes","description":"Read the persisted per-row outcomes of one import in this organization. Bounded page with a keyset cursor and an honest continuation that advances by actual rows, so a server page cap never truncates the evidence. category filters to create, merge, suppress or skip. Scope contacts:read. format=csv returns the full set as CSV. A foreign import or a missing table is an error, never empty success.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Keyset cursor from a prior response's next_cursor."},{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["create","merge","suppress","skip"]},"description":"Limit import outcomes to one kind."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"Export format."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportOutcomes"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/imports/cohorts/{cohortId}":{"get":{"operationId":"getImportCleaningCohort","summary":"Read an import identity cohort","description":"Read the safe metadata of one frozen import identity cohort by its id (returned as cohortId by the commit when the commit was preview-backed): id, preview and job references, snapshot version/fingerprint, requested cleaning channels, CAPTURED UNIQUE identity counts, a capture state and whether the separate cohort-scoped paid cleaning step is available. Never the raw email/address keys, never a billable-unit or pending-check count, and never a cleaning execution status. Scope contacts:read. A foreign or absent cohort is 404; a missing table is an error, never empty success.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:read"],"parameters":[{"name":"cohortId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The id of one import identity cohort."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportCleaningCohort"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/import/cohorts/{cohortId}/clean":{"post":{"operationId":"cleanImportCohort","summary":"Clean one import identity cohort","description":"Spends balance and cleans EXACTLY the frozen cohort's identities: the contacts matching the cohort's captured email keys and complete-address hashes, in this organization. It never runs a whole-organization verification and never accepts a caller-supplied key list. Scope email:verify and address:verify. Requires confirm true and a unique idempotency key. Nothing is charged when no cohort identity needs cleaning.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:verify","address:verify"],"parameters":[{"name":"cohortId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The id of one import identity cohort."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportCohortClean"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportCohortCleanResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/import/staged":{"post":{"operationId":"stageContactImportUpload","summary":"Stage a large contact-import upload in chunks","description":"Begin or extend a staged upload for a contact file too large to inline in one call. The first call omits stagingId and returns a staging id; later calls append a chunk with that id, and final true marks the last chunk. Stores bytes only: nothing is parsed, no contact is written and nothing is charged. The staging id is the durable reference a later import commit uses for this file. Scope contacts:write.","tags":["contacts"],"security":[{"bearerAuth":[]}],"x-required-scopes":["contacts:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportStagedUpload"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportStagedUploadResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inbox/conversations":{"get":{"operationId":"listInboxConversations","summary":"List inbox conversations","description":"Triage metadata only. Delivery addresses are omitted. Sending a reply is not available. Scope inbox:read.","tags":["inbox"],"security":[{"bearerAuth":[]}],"x-required-scopes":["inbox:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inbox/conversations/{id}":{"get":{"operationId":"getInboxConversation","summary":"Read one inbox conversation","description":"Content for triage. No delivery addresses and no send. Scope inbox:read.","tags":["inbox"],"security":[{"bearerAuth":[]}],"x-required-scopes":["inbox:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/suppressions":{"get":{"operationId":"listSuppressions","summary":"List suppression records","description":"Scope suppression:read.","tags":["suppressions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["suppression:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."},{"name":"channel","in":"query","required":false,"schema":{"type":"string","enum":["email","sms","voice","all"]},"description":"Limit suppression rows to one channel."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSuppression","summary":"Record a suppression","description":"Email, phone, or both. Reason is manual, recipient_blocks_sender, unsubscribe, or legal_request. Note is required. Scope suppression:write.","tags":["suppressions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["suppression:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/suppressions/{id}":{"patch":{"operationId":"bypassSuppression","summary":"Bypass an overridable suppression","description":"The row is kept. Note explains why. Scope suppression:write.","tags":["suppressions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["suppression:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionBypass"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionRow"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"withdrawSuppressionBypass","summary":"Withdraw a suppression bypass","description":"Puts the suppression back in force. Does not delete the row. Scope suppression:write.","tags":["suppressions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["suppression:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionRow"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/preview":{"post":{"operationId":"previewEmailCampaign","summary":"Preview an email audience and cost","description":"Does not send or charge. Audience may be all, segment, selected, or people who opened or clicked a prior email. excludeCampaignIds drops people already on those campaigns, counted once per contact. resendToNonOpenersAfterHours may be 24, true, false, or null. Scope email:draft. Price is $1 per 1,000, minimum 1 cent. accountSuppressedCount is how many otherwise-mailable addresses are already blocked for this account.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns":{"get":{"operationId":"listEmailCampaigns","summary":"List email campaigns","description":"Newest first. limit defaults to 20 and is capped at 100; page starts at 1. opened_count is unique recipients with any recorded open (including Apple MPP prefetches and machine scanners), the same number as opens.raw from /email/campaigns/{id}/clicks; it is not total open hits. metricDefinitions explains each count. Scope email:read.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCampaignList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createEmailCampaign","summary":"Create an email draft","description":"Creates a draft. Include scheduledAt only when this call should also schedule it. That also needs scope email:send and an Idempotency-Key. scheduledAt is ISO-8601 with a numeric offset or Z, at least 5 minutes ahead and no more than 366 days out. Scope email:draft.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCreateResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}":{"get":{"operationId":"getEmailCampaign","summary":"Read an email campaign","description":"Includes stored content, status, and scheduled time. Scope email:read.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCampaignDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateEmailCampaign","summary":"Revise an email draft","description":"Unscheduled drafts only. Does not change the audience. Scope email:draft.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDraftPatch"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteEmailCampaign","summary":"Delete an unsent email draft","description":"Only an unsent, unscheduled draft. Sent campaigns are kept. Scope email:draft.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/audience":{"patch":{"operationId":"replaceEmailAudience","summary":"Replace a draft audience","description":"Replaces the audience and rebuilds the recipient snapshot. Scope email:draft.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/recipients/refresh":{"post":{"operationId":"refreshEmailRecipients","summary":"Rebuild a draft recipient snapshot","description":"Uses the audience already saved on the draft. Scope email:draft.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/test":{"post":{"operationId":"sendEmailTest","summary":"Send a test of a stored email draft","description":"Sends to the key owner, an active organization member, or a verified test recipient. to or testEmails accepts up to 5 addresses. More than one recipient needs an Idempotency-Key of 16 to 128 letters, numbers, underscores, or hyphens. Scope email:test. Tests are charged.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:test"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/test-recipients":{"get":{"operationId":"listTestRecipients","summary":"List test recipients","description":"Addresses allowed to receive email test sends after they confirm. Pending addresses are not valid test destinations yet. Scope email:test. Does not return confirmation links.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:test"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRecipientList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"addTestRecipient","summary":"Add a test recipient","description":"Sends one verification email. A verified address is not emailed again. A pending address is not emailed again within ten minutes. The address cannot receive a test until it confirms. Scope email:test. Does not send a campaign or charge.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:test"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRecipientWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestRecipientEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/test-recipients/{id}":{"delete":{"operationId":"removeTestRecipient","summary":"Remove a test recipient","description":"The address can no longer receive test sends unless it is the key owner or an active member. Scope email:test. Does not send a message or change the balance.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:test"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/send":{"post":{"operationId":"sendEmailCampaign","summary":"Start a live email campaign","description":"Spends balance and starts delivery. Scope email:send. $1 per 1,000 recipients, minimum 1 cent. Do not retry an uncertain result blindly.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/schedule":{"post":{"operationId":"scheduleEmailCampaign","summary":"Schedule an email draft","description":"Does not send or charge until the scheduled time. Requires Idempotency-Key and scope email:send. scheduledAt is ISO-8601 with an offset or Z.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBody"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/unschedule":{"post":{"operationId":"unscheduleEmailCampaign","summary":"Return a scheduled email to draft","description":"Refuses a campaign that is already sending or sent. Requires Idempotency-Key and scope email:send.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional":{"get":{"operationId":"listTransactionalEmails","summary":"List transactional emails","description":"System mail for this organization. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"sendTransactionalEmail","summary":"Send a transactional email","description":"One-to-one system mail. No marketing footer. Hard bounces and complaints suppress later mail. Accepts the message and returns 202 with id and status queued before the provider call. A response in the 200 range that has id and no error is success. A replay of a completed send inside 24 hours returns 200 with id. An Idempotency-Key of 8 to 255 characters dedupes per organization for 24 hours. Scope email:transactional. Default price matches campaign email. A new organization is limited to 10 sends per minute and 200 recipients per day until those limits are changed.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalSend"}}}},"responses":{"202":{"description":"Accepted. The outcome is not final yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalAccepted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional/{id}":{"get":{"operationId":"getTransactionalEmail","summary":"Read one transactional email","description":"Status, attempt_count, next_attempt_at, and recipients. queued means the row is still waiting. The rendered body is not included. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/emails":{"get":{"operationId":"listEmailsAlias","summary":"List transactional emails (alias)","description":"Same JSON as GET /email/transactional. Scope email:transactional.","tags":["emails"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"sendEmailAlias","summary":"Send a transactional email (alias)","description":"Same JSON as POST /email/transactional. A new send returns 202. A response in the 200 range that has id and no error is success. Scope email:transactional.","tags":["emails"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalSend"}}}},"responses":{"202":{"description":"Accepted. The outcome is not final yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalAccepted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/emails/{id}":{"get":{"operationId":"getEmailAlias","summary":"Read one transactional email (alias)","description":"Same JSON as GET /email/transactional/{id}. Scope email:transactional.","tags":["emails"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional/templates":{"get":{"operationId":"listTransactionalTemplates","summary":"List transactional templates","description":"Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTransactionalTemplate","summary":"Create a transactional template","description":"Placeholders use double curly braces. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalTemplateWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional/templates/{id}":{"get":{"operationId":"getTransactionalTemplate","summary":"Read a transactional template","description":"Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateTransactionalTemplate","summary":"Update a transactional template","description":"Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalTemplateWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteTransactionalTemplate","summary":"Delete a transactional template","description":"Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional/webhooks":{"get":{"operationId":"listTransactionalWebhooks","summary":"List transactional webhook endpoints","description":"Https endpoints for delivered, bounced, and failed. The secret is not returned. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalWebhookList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createTransactionalWebhook","summary":"Create a transactional webhook endpoint","description":"Https url only. The secret is returned once. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalWebhookWrite"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalWebhookCreated"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/transactional/webhooks/{id}":{"patch":{"operationId":"updateTransactionalWebhook","summary":"Enable or disable a transactional webhook","description":"Does not rotate the secret. Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalWebhookUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionalWebhook"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteTransactionalWebhook","summary":"Delete a transactional webhook","description":"Scope email:transactional.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:transactional"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/recipients":{"get":{"operationId":"listEmailRecipients","summary":"Read email recipient outcomes","description":"Scope logs:read.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRecipientPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/events":{"get":{"operationId":"listEmailEvents","summary":"Read email delivery events","description":"Scope logs:read.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailEventPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/email/campaigns/{id}/clicks":{"get":{"operationId":"getEmailCampaignClicks","summary":"Read email opens and grouped clicks","description":"Human, Apple MPP, and machine opens for this email campaign, plus human and raw clicks. Human events are not machine and not Apple MPP, so a proxied mail fetch counts as human. An unclassified click counts as human. Apple MPP is its own bucket and is an open, so it does not reduce click counts. Machine events are the stored machine classification. opens.raw is unique recipients with any recorded open (one stored open per recipient) and equals the campaign opened_count. Click raw is every recorded click event. definitions explains each count. group_by=url, the default, groups by the normalized link: scheme and host, with the query string, the fragment, and per-recipient path tokens removed. A readable slug stays. group_by=utm_content groups by that parameter, and a click without it is null. A click stored without a link is null in either grouping. Any other group_by is rejected. Scope email:read. The campaign must belong to the key's organization.","tags":["email"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"group_by","in":"query","required":false,"schema":{"type":"string","enum":["url","utm_content"],"default":"url"},"description":"How to group clicks. url is the normalized link. utm_content groups by that parameter. Defaults to url."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailCampaignClicks"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversions":{"post":{"operationId":"recordConversion","summary":"Record an attributed conversion","description":"From an external form, site, or payment system. Scope conversions:write. campaignId, event, and externalId are required.","tags":["conversions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["conversions:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionWrite"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/conversions/sources":{"get":{"operationId":"listConversionSources","summary":"List conversion sources","description":"Donation, sign-up, and RSVP sources for the key's organization. The token is not returned. Scope conversions:write.","tags":["conversions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["conversions:write"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionSourceList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createConversionSource","summary":"Create a conversion source","description":"Returns the token and webhook URL once. A donation source uses the Anedot donation_completed signature. A sign-up or RSVP source also has a pixel URL. Scope conversions:write.","tags":["conversions"],"security":[{"bearerAuth":[]}],"x-required-scopes":["conversions:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionSourceWrite"}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversionSourceCreated"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/campaigns/{id}/report":{"get":{"operationId":"getCampaignReport","summary":"Read clicks, conversions, and throughput","description":"Human clicks by link, conversion counts and dollars, throughput, and the channel so email and SMS can be compared. A campaign with no conversions is zero. Clicks are null when the campaign is not email or text. Scope conversions:write. Email, phone, and tokens are not returned.","tags":["campaigns"],"security":[{"bearerAuth":[]}],"x-required-scopes":["conversions:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignPerformanceReport"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verification/email":{"get":{"operationId":"quoteEmailVerification","summary":"Quote an email verification run","description":"Returns how many unique addresses would be checked and the cost. Does not return the addresses. Scope email:verify.","tags":["verification"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:verify"],"parameters":[{"name":"recipientType","in":"query","required":false,"schema":{"type":"string","enum":["all","segment"]},"description":"Whose addresses to quote. Defaults to all contacts."},{"name":"segmentId","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Saved list id when recipientType is segment."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationQuote"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"runEmailVerification","summary":"Run email verification","description":"Spends balance and checks the quoted addresses. Scope email:verify.","tags":["verification"],"security":[{"bearerAuth":[]}],"x-required-scopes":["email:verify"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/verification/address":{"get":{"operationId":"quoteAddressVerification","summary":"Quote a postal address verification run","description":"All mailing contacts. Returns a quote, not the addresses. Scope address:verify.","tags":["verification"],"security":[{"bearerAuth":[]}],"x-required-scopes":["address:verify"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationQuote"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"runAddressVerification","summary":"Run postal address verification","description":"Spends balance. Scope address:verify.","tags":["verification"],"security":[{"bearerAuth":[]}],"x-required-scopes":["address:verify"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/readiness":{"get":{"operationId":"getSmsReadiness","summary":"Read texting readiness","description":"Whether the organization can text, plus blockers in plain language. Scope sms:read.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsReadiness"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/preview":{"post":{"operationId":"previewSmsCampaign","summary":"Preview a text audience and cost","description":"Does not send or charge. Short texts are 3 cents. Longer texts and pictures are 6 cents. Scope sms:draft.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns":{"get":{"operationId":"listSmsCampaigns","summary":"List text campaigns","description":"Scope sms:read.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createSmsCampaign","summary":"Create a text draft","description":"JSON for a plain text. A picture message must be multipart with an image file named image. scheduledAt is rejected here. Schedule with the schedule route. Scope sms:draft.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}":{"get":{"operationId":"getSmsCampaign","summary":"Read one text campaign","description":"Scope sms:read. Picture messages report hasMedia, not a file URL.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateSmsCampaign","summary":"Revise a text draft","description":"Name, message, or type. Audience changes use the audience route. Scope sms:draft.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/audience":{"patch":{"operationId":"replaceSmsAudience","summary":"Replace a text draft audience","description":"Replaces the audience and rebuilds the recipient snapshot for an unscheduled draft. Recalculates the recipient count and cost estimate. Does not send, schedule, or charge. A campaign that is no longer a draft is refused. Scope sms:draft.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:draft"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignEnvelope"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/test":{"post":{"operationId":"sendSmsTest","summary":"Send a text test","description":"Sends the stored draft to the key owner's verified phone. Requires Idempotency-Key and scope sms:test. Charged like a live text.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:test"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/send":{"post":{"operationId":"sendSmsCampaign","summary":"Start text delivery","description":"Spends balance and starts delivery. Requires Idempotency-Key and scope sms:send.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/schedule":{"post":{"operationId":"scheduleSmsCampaign","summary":"Schedule a text draft","description":"Does not text or charge until the scheduled time. Requires Idempotency-Key and scope sms:send.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBody"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/unschedule":{"post":{"operationId":"unscheduleSmsCampaign","summary":"Return a scheduled text to draft","description":"Refuses a campaign that is already sending or sent. Requires Idempotency-Key and scope sms:send.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsMutation"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/recipients":{"get":{"operationId":"listSmsRecipients","summary":"Read text recipient outcomes","description":"Needs both sms:read and logs:read.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read","logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsRecipientPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/events":{"get":{"operationId":"listSmsEvents","summary":"Read text delivery events","description":"Needs both sms:read and logs:read.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read","logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["queued","sending","sent","delivered","failed"]},"description":"Filter delivery events by status."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsEventPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/clicks":{"get":{"operationId":"getSmsCampaignClicks","summary":"Read per-link text clicks","description":"Clicks for each tracked link on this text campaign. Each row is the link id, the https destination, the human tap count, and the raw tap count. Human excludes a scanner. Raw includes a scanner and a second tap. A link with no taps is included with zero. Redirect tokens are not returned. Scope sms:read. The campaign must belong to the key's organization.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsCampaignClicks"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sms/campaigns/{id}/outcomes":{"get":{"operationId":"getSmsOutcomes","summary":"Read text failure counts by reason","description":"Needs both sms:read and logs:read. sampleError is plain language.","tags":["sms"],"security":[{"bearerAuth":[]}],"x-required-scopes":["sms:read","logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsOutcomes"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mail/campaigns/preview":{"post":{"operationId":"previewMailCampaign","summary":"Preview a postcard or letter","description":"Does not reserve funds or print. Scope mail:read. Postcard 4x6 is $1.19, 6x9 is $1.35, 6x11 is $1.69. A letter is $1.59. Printing cannot be recalled.","tags":["mail"],"security":[{"bearerAuth":[]}],"x-required-scopes":["mail:read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailPreviewRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mail/campaigns":{"get":{"operationId":"listMailCampaigns","summary":"List postcard and letter campaigns","description":"Scope mail:read.","tags":["mail"],"security":[{"bearerAuth":[]}],"x-required-scopes":["mail:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createMailCampaign","summary":"Create a postcard or letter draft","description":"Multipart form. mailType is postcard or letter. postcardSize is 4x6, 6x9, or 6x11. frontCreative is required. Holds balance. Requires Idempotency-Key and scope mail:draft.","tags":["mail"],"security":[{"bearerAuth":[]}],"x-required-scopes":["mail:draft"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/MailCreateForm"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mail/campaigns/{id}":{"get":{"operationId":"getMailCampaign","summary":"Read a postcard or letter campaign","description":"Configuration and progress. Creative file URLs are omitted. Scope mail:read.","tags":["mail"],"security":[{"bearerAuth":[]}],"x-required-scopes":["mail:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/mail/campaigns/{id}/launch":{"post":{"operationId":"launchMailCampaign","summary":"Submit postcards or letters for printing","description":"Spends the hold and cannot be recalled. Requires Idempotency-Key and scope mail:send.","tags":["mail"],"security":[{"bearerAuth":[]}],"x-required-scopes":["mail:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailLaunch"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/numbers":{"get":{"operationId":"listVoiceNumbers","summary":"List voice caller ids","description":"Active voice-enabled numbers for this organization. Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceNumberList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/numbers/search":{"get":{"operationId":"searchPhoneNumbers","summary":"Search available phone numbers","description":"Owner or admin. Ask the carrier marketplace for numbers this organization can buy: toll-free inventory by default, or local inventory for an areaCode and optional state. type is toll-free or local. Each result carries the one-time setup price and the monthly rental. Read-only: it reserves no funds, orders nothing, and assigns nothing; one routine API audit row is recorded. Buy a result with POST /voice/numbers/purchase. Scope settings:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:read"],"parameters":[{"name":"areaCode","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{3}$"},"description":"US area code for a local phone-number search. Ignored for a toll-free search."},{"name":"state","in":"query","required":false,"schema":{"type":"string"},"description":"Two-letter US state for a local phone-number search. Ignored for a toll-free search."},{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["toll-free","local"]},"description":"Which phone-number inventory to search. Defaults to toll-free."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumberSearchResults"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/numbers/purchase":{"post":{"operationId":"purchasePhoneNumber","summary":"Buy a toll-free phone number","description":"Owner or admin. Buy one toll-free number for this organization and charge the one-time setup fee from the organization balance. phoneNumber must be a toll-free number returned by GET /voice/numbers/search. Requires confirm true, a bounded Idempotency-Key header, and scope settings:write. A retry with the same key reuses one reservation and never orders a second number. The monthly rental is billed later by the rental job. Pass approvalId only when an operator approved this exact purchase.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:write"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumberPurchaseRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumberPurchaseResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/numbers/{id}/default":{"post":{"operationId":"setDefaultPhoneNumber","summary":"Set the default caller id","description":"Owner or admin. Set one active number in this organization as the default caller id. The number is the path id. It changes settings only: it moves no money and orders nothing. Scope settings:write.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["settings:write"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneNumberDefaultResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/assets":{"post":{"operationId":"uploadVoiceAsset","summary":"Upload a voicemail recording","description":"Multipart file field. MP3 or WAV, up to 10 MB. Returns an asset token to use when creating a voicemail draft. Scope voice:draft.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:draft"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/VoiceAssetUpload"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceAsset"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/campaigns":{"get":{"operationId":"listVoiceCampaigns","summary":"List call, voicemail, and robocall drafts","description":"Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceCampaignList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createVoiceCampaign","summary":"Create a call, voicemail, or robocall draft","description":"type is call, voicemail, or robocall. A call needs message. A voicemail or robocall needs audioAssetToken and audioDuration. Scheduling is not accepted here. Scope voice:draft. Calls, voicemail, and robocalls are 6 cents per connected started minute. Ringing is free.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceDraft"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceDraftResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/campaigns/{id}":{"get":{"operationId":"getVoiceCampaign","summary":"Read a voice campaign","description":"Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceCampaignDetail"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/campaigns/{id}/recipients":{"get":{"operationId":"listVoiceRecipients","summary":"Read voice recipient outcomes","description":"Needs both voice:read and logs:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read","logs:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceRecipientPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/campaigns/{id}/launch":{"post":{"operationId":"launchVoiceCampaign","summary":"Launch voicemail delivery","description":"Spends balance. Requires Idempotency-Key and scope voice:send. A drop reserves 42 cents.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceLaunchResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/campaigns/{id}/recording-test":{"post":{"operationId":"testVoiceRobocallDraft","summary":"Play a robocall draft recording on the key owner's registered phone","description":"Plays this draft's saved recording to the API key owner's registered phone. The draft is not launched and the list is not dialed. Requires Idempotency-Key and scope voice:send.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:send"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalOptional"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceRecordingTest"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/robocall/test":{"post":{"operationId":"testVoiceRobocall","summary":"Place a personal robocall test","description":"Places one standalone robocall of an organization-owned recording to the API key owner's registered phone. Never attaches to a campaign. Requires Idempotency-Key and scope voice:send.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:send"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceRobocallTestRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceRecordingTest"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/calls":{"post":{"operationId":"placeVoiceCall","summary":"Place a one-to-one call","description":"contactId is required. The operator is dialed first. If the operator does not answer, the contact is not dialed. Requires Idempotency-Key and scope voice:send.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:send"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceCallCreate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStart"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/calls/active":{"get":{"operationId":"getActiveVoiceCall","summary":"Read the active call for this key's owner","description":"Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallActive"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/calls/{id}":{"get":{"operationId":"getVoiceCall","summary":"Read a call session","description":"Scope voice:read. Carrier call ids are not included.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStart"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/power-dialer/sessions":{"get":{"operationId":"listPowerDialerSessions","summary":"List power dialer sessions","description":"Sessions for this key's owner. Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerDialerList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"openPowerDialerSession","summary":"Open or resume a power dialer session","description":"Body is campaignId. The operator cannot set a bridge phone. Scope voice:draft. 6 cents per operator-connected started minute, up to $14.40.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:draft"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerDialerOpen"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerDialerOpened"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/power-dialer/sessions/{sessionId}":{"get":{"operationId":"getPowerDialerSession","summary":"Read a power dialer session","description":"Scope voice:read.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:read"],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Power dialer session id."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerDialerSession"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voice/power-dialer/sessions/{sessionId}/next":{"post":{"operationId":"dialNextPowerDialerContact","summary":"Dial the next power dialer contact","description":"Hangs up the current contact only. Requires Idempotency-Key and scope voice:send.","tags":["voice"],"security":[{"bearerAuth":[]}],"x-required-scopes":["voice:send"],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Power dialer session id."},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PowerDialerOpened"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/exports/contacts":{"get":{"operationId":"exportContacts","summary":"Export contacts","description":"JSON or CSV, paged. Scope exports:read.","tags":["exports"],"security":[{"bearerAuth":[]}],"x-required-scopes":["exports:read"],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","csv"],"default":"json"},"description":"Export format."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/audit-log":{"get":{"operationId":"listAuditLog","summary":"Read this organization's audit log","description":"This organization's audit log, newest first: actions taken with API keys and connected agents, plus every paid or bulk action from any source (dashboard, API, MCP, cron, import). Paid and bulk actions are list cleaning and email or address verification, campaign launches, phone number and 10DLC purchases, balance holds and contact imports. Each of those entries is written when the action starts (or is blocked) and updated with its outcome, and carries source, outcome, estimated and actual cost in cents, the target list or segment (ids and names), counts (requested, processed, succeeded, failed), started_at, finished_at and the request id. Filter by action, source, outcome, actor_user_id, key_id (an API key id), request_id, paid_only, since and until. Entries never contain contact emails, phone numbers, addresses or message bodies. Always scoped to the credential's organization. Read-only: records one routine audit row. Scope logs:read.","tags":["audit-log"],"security":[{"bearerAuth":[]}],"x-required-scopes":["logs:read"],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number, starting at 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."},{"name":"action","in":"query","required":false,"schema":{"type":"string"},"description":"Only this action, such as email_verification.run. End with * to match a prefix, such as campaign_launch.*."},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["ui","api","mcp","cron","import","system"]},"description":"Only entries started from this source."},{"name":"outcome","in":"query","required":false,"schema":{"type":"string","enum":["started","succeeded","partial","failed","blocked"]},"description":"Only paid or bulk actions with this outcome."},{"name":"actor_user_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Only entries by this user."},{"name":"key_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Only entries made with this API key."},{"name":"request_id","in":"query","required":false,"schema":{"type":"string"},"description":"Only entries from this request id."},{"name":"paid_only","in":"query","required":false,"schema":{"type":"boolean"},"description":"true returns only paid and bulk actions (list cleaning, verification, launches, purchases, balance holds, imports)."},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Entries at or after this ISO 8601 time."},{"name":"until","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Entries before this ISO 8601 time."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration/brand":{"get":{"operationId":"getBrandRegistration","summary":"Read texting brand-registration status","description":"This organization's stored 10DLC brand filing state, the one-time brand filing fee, the organization balance, and whether the credential is the active, fully-set-up owner (role-and-setup eligibility only; not spending authority). It is the locally stored state, not a live carrier reconciliation, and never returns carrier identifiers, raw payloads, verification tokens, or a full EIN. Paid brand submission is available through POST /api/v1/registration/brand when the credential holds registration:submit and the active organization owner has completed setup; owner_and_setup_eligible here is role-and-setup eligibility only, not a credential grant. Files nothing, charges nothing, creates no profile, assigns no number; one routine API audit row is recorded. Scope registration:read.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandRegistrationStatus"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"submitBrandRegistration","summary":"File a texting brand registration","description":"Owner-only 10DLC brand filing. Only the active, fully-set-up organization owner may file; an admin cannot file. It charges the non-refundable one-time brand filing fee from the server (never the caller), builds the exact packet from the saved identity and the credential owner's own representative fallbacks, and requires confirm-equivalent fee_acknowledged, a bounded Idempotency-Key header, and scope registration:submit. A repeat with the same packet and key is already on file and charges nothing; an uncertain carrier outcome is never retried blindly. Send the same brand fields to POST /agent/approvals when this key requires an operator approval, then pass the returned id as approvalId.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:submit"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandSubmitRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandSubmitResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration/brand/preview":{"post":{"operationId":"previewBrandRegistration","summary":"Preview texting brand-registration validation","description":"Validate would-be brand filing details against the saved settings and return the required fixes and the authoritative filing fee, exactly like the dashboard's business-information step. Omitted fields fall back to the saved value or the credential owner's own details; an empty string clears a value. Validation only: it reserves nothing, writes no business or billing state, charges nothing, and guarantees no carrier acceptance; one routine API audit row is recorded. The response's `ready` flag means the packet passed field validation only, not that the organization is already filed, permitted, or funded. Paid submission is available through POST /api/v1/registration/brand. Scope registration:read.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:read"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandPreviewRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandPreview"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration/campaign":{"get":{"operationId":"getCampaignRegistration","summary":"Read texting campaign-registration readiness","description":"Owner or admin only, matching the dashboard's campaign surface. This organization's stored 10DLC campaign-registration readiness: the current filing status, rejection and retry notes, the frozen filed packet, the resumable draft, the persisted free site-check history, the authoritative campaign review fee, and whether setup is complete. It is the locally stored state, not a live carrier reconciliation, and never returns carrier identifiers, raw provider payloads, verification tokens, or the raw registration row; your own brand names, URLs, and copy are preserved verbatim. already_filed means a carrier campaign reference is recorded, not approval or delivery, and a missing reference does not prove no filing occurred; confirmation_required or submitting mean an existing attempt must not be filed again, and none of these flags establish whether a fee was charged. Paid campaign filing is available through submit_texting_campaign_registration (POST /api/v1/registration/campaign/submit) when the credential holds registration:submit. It files nothing, charges nothing, creates no profile, assigns no number; one routine API audit row is recorded. Scope registration:read.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRegistrationStatus"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration/campaign/site-check":{"post":{"operationId":"checkCampaignSite","summary":"Run the free campaign website preflight","description":"Owner or admin only, and the organization must be fully set up. Free website-compliance preflight for this organization's campaign: validate opt_in_url, privacy_policy_url, terms_url (optional opt_in_screenshot_url), fetch the live public pages, return the same carrier checklist the paid submit enforces, and append one immutable history row stamped with the organization and check time. It makes outbound reads of your public pages and appends history, so a repeat is a new timestamped record rather than a no-op. A failed history write is surfaced as an error, never presented as durable evidence. It charges nothing, files nothing with any carrier, creates no profile, and assigns no number. Scope registration:prepare.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:prepare"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSiteCheckRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSiteCheckResult"}}}},"400":{"description":"The request was refused before any effect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSiteCheckFailure"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"The action ran but its result is not durable, or it could not complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSiteCheckFailure"}}}}}}},"/registration/campaign/draft":{"put":{"operationId":"saveCampaignDraft","summary":"Save a texting campaign compliance draft","description":"Owner or admin only, and the organization must be fully set up. Saves this organization's texting campaign compliance draft: opt_in_url, privacy_policy_url, terms_url, and the optional opt_in_screenshot_url, opt_in_description, help_email. It writes the same draft the paid filing later reads. A supplied field is written, an omitted field keeps its stored value, and an empty string clears a saved value. A supplied help_email must be a valid address, and an empty one never erases the stored shared inbox. An opt_in_description that does not name your form, privacy, and terms URLs plus STOP and HELP is refused. It is free: it charges nothing, files nothing with any carrier, creates no profile, and assigns no number, and it records one routine API audit row. The free preflight is POST /registration/campaign/site-check and the paid filing is POST /registration/campaign/submit. Scope registration:prepare.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:prepare"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDraftRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDraftSaved"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration/campaign/submit":{"post":{"operationId":"submitCampaignRegistration","summary":"File the texting campaign registration","description":"Owner or admin only, and the organization must be fully set up. Files this organization's 10DLC campaign registration and charges the non-refundable review fee for this submission from the server, never the caller. It requires confirm-equivalent compliance_acknowledged true and fee_acknowledged true, a bounded Idempotency-Key header, and scope registration:submit. Before any fee is charged it validates the saved draft, fetches the three filed public pages, and runs the same carrier checklist as POST /registration/campaign/site-check; it then reconciles the stored filing state and fails closed with 409 when an existing attempt cannot be interpreted, so an uncertain outcome is never retried blindly. When the business registration is not yet approved it saves the draft as queued and charges nothing. A repeat with the same idempotency_key is already on file and charges nothing. Send the same filing to POST /agent/approvals first when this key requires an operator approval, then pass the returned id as approval_id.","tags":["registration"],"security":[{"bearerAuth":[]}],"x-required-scopes":["registration:submit"],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":255},"description":"Unique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSubmitRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignSubmitResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/billing/balance":{"get":{"operationId":"getBillingBalance","summary":"Read organization funds","description":"The real available balance (active holds already deducted) and the outstanding held reservations as a separate number; holds are never subtracted twice. A failed read is an error, not a zero. Active owner or admin. Read-only; charges nothing and creates no payment profile. Scope billing:read.","tags":["billing"],"security":[{"bearerAuth":[]}],"x-required-scopes":["billing:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingBalance"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/billing/transactions":{"get":{"operationId":"listBillingTransactions","summary":"Page the organization ledger","description":"Newest first, bounded offset/limit, exact total and has-more. Returns the public ledger id, type, whole-cent amount, running balance, description, and timestamp only, with no processor identifiers, idempotency keys, metadata, or another member's private settings. Active owner or admin. Scope billing:read.","tags":["billing"],"security":[{"bearerAuth":[]}],"x-required-scopes":["billing:read"],"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"maximum":1000000,"default":0},"description":"How many newest entries to skip."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":100},"description":"Page size. The server caps this."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingTransactionPage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/billing/auto-topup":{"get":{"operationId":"getAutoTopUpSettings","summary":"Read Auto Top-Up configuration","description":"The saved automatic-replenishment configuration for this organization, including the saved card's brand, last 4 digits, and expiry, and never a card number or identifier. Active owner or admin. Scope billing:read.","tags":["billing"],"security":[{"bearerAuth":[]}],"x-required-scopes":["billing:read"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingAutoTopUp"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"updateAutoTopUpSettings","summary":"Save Auto Top-Up configuration","description":"Saves the configuration exactly like Account, Auto Top-Up. enabled true authorizes future automatic charges against the already-saved, already-authorized card per the threshold, amount, daily caps and cooldown; it does not charge now, add or remove a card, or deposit funds. Enabling requires a card already on file. The trigger balance is 500–100000 cents and the amount is 1000–100000 cents, whole cents. Saving the same configuration twice is the same as once. Active owner or admin. Scope billing:write.","tags":["billing"],"security":[{"bearerAuth":[]}],"x-required-scopes":["billing:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingAutoTopUpUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingAutoTopUp"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/invitations/{id}/resend":{"post":{"operationId":"resendTeamInvitation","summary":"Re-queue a pending invitation email","description":"Re-queues the invitation email for a still-pending invitation in the credential's organization. NOT idempotent: there is no request-key store and each call is a new email request, exactly like the dashboard's re-queue action. Sends no email itself and moves no money. If the outcome cannot be confirmed, read the current invitation state rather than retrying automatically. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationAction"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/invitations/{id}/cancel":{"post":{"operationId":"cancelTeamInvitation","summary":"Cancel a pending invitation","description":"Cancels a still-pending invitation in the credential's organization; the person can be invited again afterwards. Cancelling an invitation that is already accepted, cancelled, or dismissed is refused. Sends nothing and moves no money. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationAction"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/members/{id}":{"patch":{"operationId":"changeTeamMemberRole","summary":"Change a member's role","description":"Changes an ordinary member's role between admin and member in the credential's organization. The target is the path id; the body accepts only role. Promotion to owner is refused, the organization owner cannot be changed, and you cannot change your own role. The result is the live membership read back; an unconfirmable readback is reported as uncertain, not as success or a proven no-write. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberRoleUpdate"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"removeTeamMember","summary":"Remove an ordinary member","description":"Removes an ordinary member from the credential's organization, ending their membership. The organization owner cannot be removed, you cannot remove yourself, and the last active admin cannot be removed. An optional note is recorded on the audit trail. Removes a membership only: it does not delete the account, transfer data, or move money. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberNote"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/members/{id}/suspend":{"post":{"operationId":"suspendTeamMember","summary":"Suspend an ordinary member","description":"Suspends an ordinary active member in the credential's organization, dropping them to read-only. The organization owner cannot be suspended, you cannot suspend yourself, and the last active admin cannot be suspended. An optional note is recorded on the audit trail. The result is the live membership read back. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberNote"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/team/members/{id}/reactivate":{"post":{"operationId":"reactivateTeamMember","summary":"Reactivate a suspended member","description":"Reactivates a suspended member in the credential's organization. The organization owner cannot be acted on and you cannot reactivate yourself. A member who is not suspended is refused. An optional note is recorded on the audit trail. The result is the live membership read back. Scope team:manage.","tags":["team"],"security":[{"bearerAuth":[]}],"x-required-scopes":["team:manage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Campaign Commander id for this resource."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberNote"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Organization balance is too low","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks the required scope, or organization setup is incomplete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict, such as a duplicate contact or a campaign that is no longer a draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Campaign Commander could not complete the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}