{"openapi":"3.0.0","paths":{"/admin/audit-logs":{"get":{"description":"Newest first. Filter by actor email, exact action, and a created-at range.","operationId":"AuditController_list","parameters":[{"name":"actor","required":false,"in":"query","schema":{"type":"string","maxLength":200}},{"name":"action","required":false,"in":"query","schema":{"type":"string","maxLength":200}},{"name":"from","required":false,"in":"query","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},{"name":"to","required":false,"in":"query","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},{"name":"page","required":false,"in":"query","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","required":false,"in":"query","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"One page of entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuditLogPage"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Audit log, filterable","tags":["Admin — audit"]}},"/admin/accounts":{"get":{"operationId":"AccountsAdminController_list","parameters":[{"name":"search","required":false,"in":"query","schema":{"type":"string","maxLength":200}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]}},{"name":"page","required":false,"in":"query","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","required":false,"in":"query","schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"One page of accounts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Accounts registry","tags":["Admin — accounts"]}},"/admin/accounts/{id}":{"get":{"operationId":"AccountsAdminController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The account detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountDetail"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such account."}},"security":[{"session":[]}],"summary":"One account, with wallet, KYC history, keys and recent activity","tags":["Admin — accounts"]}},"/admin/accounts/{id}/suspend":{"post":{"description":"ACTIVE → SUSPENDED. Audited with the mandatory reason.","operationId":"AccountsAdminController_suspend","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountStatusChange"}}}},"responses":{"200":{"description":"The updated account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountDetail"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such account."},"409":{"description":"The account is not in a state that can be suspended."}},"security":[{"session":[]}],"summary":"Suspend an account","tags":["Admin — accounts"]}},"/admin/accounts/{id}/reactivate":{"post":{"description":"SUSPENDED → ACTIVE (if it was verified) or PENDING_KYC (if not). Audited.","operationId":"AccountsAdminController_reactivate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountStatusChange"}}}},"responses":{"200":{"description":"The updated account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAccountDetail"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such account."},"409":{"description":"The account is not suspended."}},"security":[{"session":[]}],"summary":"Reactivate a suspended account","tags":["Admin — accounts"]}},"/auth/signup":{"post":{"description":"Creates the account, its owner user and its wallet, and returns a session. The new account starts at PENDING_KYC.","operationId":"AuthController_signup","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}}},"responses":{"201":{"description":"Account created; the caller is signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthSession"}}}},"409":{"description":"That email address already has an account."}},"summary":"Create an account","tags":["Auth"]}},"/auth/login":{"post":{"operationId":"AuthController_login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthSession"}}}},"401":{"description":"Wrong email or password. The two are not distinguished."}},"summary":"Sign in","tags":["Auth"]}},"/auth/password-reset":{"post":{"description":"Emails a one-time reset link if the address belongs to an account. Answers 202 either way — the response does not reveal whether the address is registered.","operationId":"AuthController_requestPasswordReset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetRequest"}}}},"responses":{"202":{"description":"Accepted. A link has been sent if, and only if, the address has an account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetAcknowledgement"}}}}},"summary":"Request a password reset link","tags":["Auth"]}},"/auth/password-reset/confirm":{"post":{"description":"One-time: the token is spent on success, and the account’s other outstanding reset tokens are invalidated with it.","operationId":"AuthController_confirmPasswordReset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetConfirm"}}}},"responses":{"200":{"description":"The password has been changed. Sign in with it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetAcknowledgement"}}}},"400":{"description":"The reset link is unknown, expired or has already been used."}},"summary":"Set a new password using a reset link","tags":["Auth"]}},"/auth/me":{"get":{"description":"Re-read from the database on every call, so `accountStatus` reflects a KYC approval or suspension that happened after the token was issued.","operationId":"AuthController_me","parameters":[],"responses":{"200":{"description":"The authenticated user and their account status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthenticatedUser"}}}}},"security":[{"session":[]}],"summary":"The current principal","tags":["Auth"]}},"/admin/providers":{"get":{"description":"Every configurable field with a masked preview, where its value currently comes from (stored, environment, or unset), and who last changed it. Secrets are never returned in plaintext by this or any other endpoint.","operationId":"ProvidersController_list","parameters":[],"responses":{"200":{"description":"The configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProviderConfigList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Provider configuration, masked","tags":["Admin — providers"]}},"/admin/providers/{provider}/{key}":{"put":{"description":"Encrypted at rest and audited with the mandatory reason. A stored value takes precedence over the deployment environment variable of the same name.","operationId":"ProvidersController_put","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProviderCredentialUpdate"}}}},"responses":{"200":{"description":"The updated configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProviderConfigList"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such provider field."}},"security":[{"session":[]}],"summary":"Store or rotate one credential","tags":["Admin — providers"]},"delete":{"description":"Removes the stored value so the deployment environment variable takes over again. Audited. Does not unset the integration.","operationId":"ProvidersController_clear","parameters":[{"name":"provider","required":true,"in":"path","schema":{"type":"string"}},{"name":"key","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProviderCredentialDelete"}}}},"responses":{"200":{"description":"The updated configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProviderConfigList"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such provider field."}},"security":[{"session":[]}],"summary":"Clear a stored credential","tags":["Admin — providers"]}},"/kyc/uploads":{"post":{"description":"Documents go straight from the browser to MinIO under the returned policy (decisions.md D12) — no identity document passes through this API.","operationId":"KycController_createUploadTarget","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycUploadTargetRequest"}}}},"responses":{"200":{"description":"A short-lived presigned POST policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycUploadTarget"}}}}},"security":[{"session":[]}],"summary":"Get a presigned upload target","tags":["KYC"]}},"/kyc":{"post":{"operationId":"KycController_submit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionRequest"}}}},"responses":{"201":{"description":"Submitted; the account stays PENDING_KYC until an admin reviews it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionSummary"}}}},"409":{"description":"A submission is already pending review."}},"security":[{"session":[]}],"summary":"Submit uploaded documents for review","tags":["KYC"]},"get":{"operationId":"KycController_list","parameters":[],"responses":{"200":{"description":"Every submission this account has made.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionSummaryList"}}}}},"security":[{"session":[]}],"summary":"Submission history, including rejection reasons","tags":["KYC"]}},"/admin/kyc/submissions":{"get":{"operationId":"KycAdminController_listPending","parameters":[],"responses":{"200":{"description":"Submissions awaiting review.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionSummaryList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"The review queue, oldest first","tags":["Admin — KYC"]}},"/admin/kyc/submissions/{id}":{"get":{"description":"The links are short-lived — they should not outlive the review.","operationId":"KycAdminController_getForReview","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The submission and its documents.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionForReview"}}}},"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such submission."}},"security":[{"session":[]}],"summary":"One submission, with presigned document links","tags":["Admin — KYC"]}},"/admin/kyc/submissions/{id}/approve":{"post":{"description":"Moves the account to ACTIVE. Audited against the reviewing admin.","operationId":"KycAdminController_approve","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycApprovalRequest"}}}},"responses":{"201":{"description":"The reviewed submission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Approve","tags":["Admin — KYC"]}},"/admin/kyc/submissions/{id}/reject":{"post":{"description":"The reason is mandatory and is shown to the client.","operationId":"KycAdminController_reject","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycRejectionRequest"}}}},"responses":{"201":{"description":"The reviewed submission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KycSubmissionSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Reject","tags":["Admin — KYC"]}},"/wallet":{"get":{"operationId":"WalletController_get","parameters":[],"responses":{"200":{"description":"The account’s wallet, in MWK decimal strings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletSummary"}}}}},"security":[{"session":[]}],"summary":"Balance and reserved credit","tags":["Wallet"]}},"/wallet/live-eligibility":{"get":{"description":"The same check `POST /api-keys` applies (decisions.md D4, D5), exposed so the dashboard can explain a disabled button instead of failing the click.","operationId":"WalletController_getLiveEligibility","parameters":[],"responses":{"200":{"description":"Eligibility, with the reason when it is not met.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveKeyEligibility"}}}}},"security":[{"session":[]}],"summary":"Whether a live API key may be issued","tags":["Wallet"]}},"/wallet/transactions":{"get":{"description":"Keyset-paginated. Auto-refunds appear as their own REFUND line.","operationId":"WalletController_listTransactions","parameters":[{"name":"limit","required":false,"in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string","minLength":1}},{"name":"type","required":false,"in":"query","schema":{"type":"string","enum":["TOPUP","DEBIT","REFUND","ADJUSTMENT"]}}],"responses":{"200":{"description":"A page of ledger entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletTransactionPage"}}}}},"security":[{"session":[]}],"summary":"Ledger, newest first","tags":["Wallet"]}},"/admin/accounts/{accountId}/wallet":{"get":{"operationId":"WalletAdminController_get","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Any account’s wallet","tags":["Admin — wallets"]}},"/admin/accounts/{accountId}/wallet/min-live-balance":{"patch":{"description":"Per-account override of the platform default (decisions.md D5). Audited.","operationId":"WalletAdminController_setMinLiveBalance","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MinLiveBalanceUpdate"}}}},"responses":{"200":{"description":"The updated wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Override this account’s live-send threshold","tags":["Admin — wallets"]}},"/admin/accounts/{accountId}/wallet/adjust":{"post":{"description":"Signed amount; the mandatory note is recorded in the audit log.","operationId":"WalletAdminController_adjust","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletAdjustRequest"}}}},"responses":{"200":{"description":"The updated wallet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Manually adjust an account’s wallet balance","tags":["Admin — wallets"]}},"/wallet/topup":{"post":{"description":"Prompts the given handset to approve a mobile-money collection through InfiPay (decisions.md D13). Returns immediately with a reference and a PENDING status — poll `GET /wallet/topup/{reference}` until it resolves. The balance moves when InfiPay confirms the collection, not here.","operationId":"PaymentsController_initiateTopup","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupRequest"}}}},"responses":{"200":{"description":"The collection has been pushed to the payer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupInitiation"}}}},"502":{"description":"InfiPay could not be reached or rejected the request."},"503":{"description":"InfiPay is not configured on this deployment."}},"security":[{"session":[]}],"summary":"Start a wallet top-up","tags":["Payments"]}},"/wallet/topup/{reference}":{"get":{"description":"Fetches the attempt from InfiPay and credits the wallet if the collection completed. Idempotent — polling this endpoint is the intended way to follow a top-up.","operationId":"PaymentsController_checkTopupStatus","parameters":[{"name":"reference","required":true,"in":"path","description":"The reference returned by POST /wallet/topup.","schema":{"type":"string"}}],"responses":{"200":{"description":"The attempt’s current state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupStatusResult"}}}},"403":{"description":"That top-up belongs to another account."},"404":{"description":"Unknown top-up reference."}},"security":[{"session":[]}],"summary":"Check a wallet top-up","tags":["Payments"]}},"/admin/pricing-rules":{"get":{"description":"Rates are versioned by append (decisions.md D3): superseded rules stay, with a status saying so.","operationId":"PricingAdminController_list","parameters":[{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}},{"name":"country","required":false,"in":"query","schema":{"type":"string","pattern":"^[A-Z]{2}$"}},{"name":"network","required":false,"in":"query","schema":{"type":"string","maxLength":40,"pattern":"^[A-Z0-9]+(?:_[A-Z0-9]+)*$"}},{"name":"includeSuperseded","required":false,"in":"query","schema":{"default":"false","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"Matching rules.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingRuleList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Pricing rules","tags":["Admin — pricing"]},"post":{"description":"There is no PATCH: repricing means posting a new rule and leaving the old row in place.","operationId":"PricingAdminController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingRuleCreate"}}}},"responses":{"201":{"description":"The new rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingRuleSummary"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Create a rule — and the way a route is repriced","tags":["Admin — pricing"]}},"/admin/pricing-rules/coverage":{"get":{"description":"An unpriced route is rejected at send time rather than guessed at (D3), so this is the list of sends that would currently fail.","operationId":"PricingAdminController_coverage","parameters":[],"responses":{"200":{"description":"Coverage per channel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingCoverageList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Which routes are priced, and what is exposed","tags":["Admin — pricing"]}},"/admin/pricing-rules/resolve":{"get":{"description":"Runs the same resolver the send pipeline uses — a re-implementation for the UI would answer a different question.","operationId":"PricingAdminController_resolve","parameters":[{"name":"channel","required":true,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}},{"name":"country","required":false,"in":"query","schema":{"default":null,"nullable":true,"type":"string","pattern":"^[A-Z]{2}$"}},{"name":"network","required":false,"in":"query","schema":{"default":null,"nullable":true,"type":"string","maxLength":40,"pattern":"^[A-Z0-9]+(?:_[A-Z0-9]+)*$"}},{"name":"at","required":false,"in":"query","schema":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}}],"responses":{"200":{"description":"Priced, or explicitly unpriced.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceResolution"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"What a route would cost","tags":["Admin — pricing"]}},"/admin/pricing-rules/{id}":{"delete":{"description":"The only removal there is. Refused once the rule has taken effect.","operationId":"PricingAdminController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Cancelled."},"403":{"description":"SUPER_ADMIN only."},"409":{"description":"The rule is already in effect and is now history."}},"security":[{"session":[]}],"summary":"Cancel a scheduled rate change","tags":["Admin — pricing"]}},"/api-keys":{"get":{"operationId":"ApiKeysController_list","parameters":[{"name":"environment","required":false,"in":"query","schema":{"type":"string","enum":["SANDBOX","LIVE"]}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["ACTIVE","REVOKED"]}}],"responses":{"200":{"description":"Keys, without secrets — those are unrecoverable by design.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"}}}}},"security":[{"session":[]}],"summary":"This account’s keys","tags":["API keys"]},"post":{"description":"The only response in this API containing a key secret. It is stored as a peppered hash, so a client who loses it rotates rather than re-reads.","operationId":"ApiKeysController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"}}}},"responses":{"201":{"description":"The new key, with its secret shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyWithSecret"}}}},"403":{"description":"A LIVE key was requested before KYC approval and the minimum balance (D4, D5)."}},"security":[{"session":[]}],"summary":"Issue a key","tags":["API keys"]}},"/api-keys/{id}/rotate":{"post":{"description":"The old secret stops authenticating the instant the new one is issued — rotation is the response to a disclosed key, so there is no overlap window. To cut over gradually instead, create a second key, deploy it, then revoke the first.","operationId":"ApiKeysController_rotate","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRotate"}}}},"responses":{"201":{"description":"The new key (with secret) and the one it replaces.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRotation"}}}},"404":{"description":"No such key on this account."}},"security":[{"session":[]}],"summary":"Mint a replacement and revoke the original","tags":["API keys"]}},"/api-keys/{id}/revoke":{"post":{"description":"Immediate and irreversible. The row remains so past messages stay attributable.","operationId":"ApiKeysController_revoke","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The revoked key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"}}}},"404":{"description":"No such key on this account."}},"security":[{"session":[]}],"summary":"Revoke a key","tags":["API keys"]}},"/v1/me":{"get":{"description":"What key am I holding and what may it do? Costs nothing and consumes no message — the first call a copy-paste snippet makes.","operationId":"V1IdentityController_me","parameters":[],"responses":{"200":{"description":"The key’s account, environment and scopes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyIdentity"}}}},"401":{"description":"Missing, unknown or revoked key."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Verify a key","tags":["Send API (v1)"]}},"/templates":{"get":{"operationId":"TemplatesController_list","parameters":[{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}}],"responses":{"200":{"description":"Templates, by name.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateList"}}}}},"security":[{"session":[]}],"summary":"This account’s templates","tags":["Templates"]},"post":{"description":"`variables` in the response is extracted from the stored body and subject, not echoed — it tells the client exactly which names their next send must supply.","operationId":"TemplatesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreate"}}}},"responses":{"201":{"description":"The created template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Placeholder syntax outside the supported subset, or a subject on an SMS template."},"409":{"description":"This account already has a template with that name."}},"security":[{"session":[]}],"summary":"Create a template","tags":["Templates"]}},"/templates/{templateId}":{"get":{"operationId":"TemplatesController_get","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"404":{"description":"No such template on this account."}},"security":[{"session":[]}],"summary":"One template","tags":["Templates"]},"patch":{"description":"Messages already sent or scheduled keep their own rendered text — editing here cannot change what they say.","operationId":"TemplatesController_update","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateUpdate"}}}},"responses":{"200":{"description":"The updated template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"404":{"description":"No such template on this account."}},"security":[{"session":[]}],"summary":"Edit a template","tags":["Templates"]},"delete":{"description":"Messages that used it keep their text and lose only the pointer.","operationId":"TemplatesController_remove","parameters":[{"name":"templateId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The deleted template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"404":{"description":"No such template on this account."}},"security":[{"session":[]}],"summary":"Delete a template","tags":["Templates"]}},"/admin/accounts/{accountId}/suppressions":{"get":{"description":"Newest first. Destinations are stored normalised (E.164 for SMS, lower-cased for email) and the `destination` filter is normalised the same way before matching.","operationId":"SuppressionsAdminController_list","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string","minLength":1}},{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}},{"name":"reason","required":false,"in":"query","schema":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]}},{"name":"destination","required":false,"in":"query","schema":{"type":"string","minLength":1,"maxLength":320}}],"responses":{"200":{"description":"One page of suppressions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionList"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"One account's opt-out list","tags":["Admin — suppressions"]},"post":{"operationId":"SuppressionsAdminController_add","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionCreate"}}}},"responses":{"201":{"description":"The new suppression.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Suppression"}}}},"403":{"description":"SUPER_ADMIN only."},"409":{"description":"This destination is already suppressed for this account."}},"security":[{"session":[]}],"summary":"Suppress a destination for this account","tags":["Admin — suppressions"]}},"/admin/accounts/{accountId}/suppressions/{id}":{"delete":{"description":"Resumes messaging a destination that had opted out. Audited with the full deleted row, since nothing else will record that it existed.","operationId":"SuppressionsAdminController_remove","parameters":[{"name":"accountId","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"403":{"description":"SUPER_ADMIN only."},"404":{"description":"No such suppression on this account."}},"security":[{"session":[]}],"summary":"Lift a suppression","tags":["Admin — suppressions"]}},"/v1/sms/send":{"post":{"description":"Asynchronous: returns once the row is written and the credit reserved. The outcome arrives on your webhook. Supply `templateId` + `variables`, or `message`, but not both. A `scheduledFor` in the future queues it for the sweep.","operationId":"SendController_sendSms","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection. A repeat of the same key on the same account returns the original message instead of sending a second one.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsSendRequest"}}}},"responses":{"202":{"description":"Accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendAccepted"}}}},"400":{"description":"Unpriced route, invalid recipient, or template variables not satisfied."},"401":{"description":"Missing, unknown or revoked API key."},"402":{"description":"Insufficient wallet balance for this send."},"403":{"description":"The key lacks the scope this channel requires."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Send one SMS","tags":["Send API (v1)"]}},"/v1/email/send":{"post":{"description":"As `POST /v1/sms/send`. An inline email needs both `subject` and `body`; a templated one needs neither.","operationId":"SendController_sendEmail","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection. A repeat of the same key on the same account returns the original message instead of sending a second one.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendRequest"}}}},"responses":{"202":{"description":"Accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendAccepted"}}}},"400":{"description":"Unpriced route, invalid recipient, or template variables not satisfied."},"401":{"description":"Missing, unknown or revoked API key."},"402":{"description":"Insufficient wallet balance for this send."},"403":{"description":"The key lacks the scope this channel requires."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Send one email","tags":["Send API (v1)"]}},"/v1/sms/bulk":{"post":{"description":"One `Message` row and one queue job per recipient (decisions.md D9), created in a single all-or-nothing transaction: a list the wallet cannot fully cover leaves zero rows behind. Recipients arrive as an array or as `recipientsCsv`. There is no built-in cap (D10).","operationId":"SendController_sendSmsBulk","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection. A repeat of the same key on the same account returns the original message instead of sending a second one.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsBulkSendRequest"}}}},"responses":{"202":{"description":"The whole batch was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendAccepted"}}}},"400":{"description":"Any unusable recipient row rejects the whole batch — see POST /messages/bulk-preview."},"401":{"description":"Missing, unknown or revoked API key."},"402":{"description":"Insufficient wallet balance for this send."},"403":{"description":"The key lacks the scope this channel requires."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Send SMS to many recipients","tags":["Send API (v1)"]}},"/v1/email/bulk":{"post":{"description":"One `Message` row and one queue job per recipient (decisions.md D9), created in a single all-or-nothing transaction: a list the wallet cannot fully cover leaves zero rows behind. Recipients arrive as an array or as `recipientsCsv`. There is no built-in cap (D10).","operationId":"SendController_sendEmailBulk","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection. A repeat of the same key on the same account returns the original message instead of sending a second one.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailBulkSendRequest"}}}},"responses":{"202":{"description":"The whole batch was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendAccepted"}}}},"400":{"description":"Any unusable recipient row rejects the whole batch — see POST /messages/bulk-preview."},"401":{"description":"Missing, unknown or revoked API key."},"402":{"description":"Insufficient wallet balance for this send."},"403":{"description":"The key lacks the scope this channel requires."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Send email to many recipients","tags":["Send API (v1)"]}},"/v1/messages/{messageId}/cancel":{"post":{"description":"Refunds the reservation. Losing the race against the sweep is a 409, not a silent success.","operationId":"SendController_cancelScheduled","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection. A repeat of the same key on the same account returns the original message instead of sending a second one.","required":false,"schema":{"type":"string"}},{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The cancelled message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"401":{"description":"Missing, unknown or revoked API key."},"402":{"description":"Insufficient wallet balance for this send."},"403":{"description":"The key lacks the scope this channel requires."},"404":{"description":"No such message on this account."},"409":{"description":"Already released to the queue, or not scheduled at all."},"429":{"description":"Per-key rate limit exceeded."}},"security":[{"apiKey":[]}],"summary":"Cancel a scheduled message","tags":["Send API (v1)"]}},"/send/sms":{"post":{"description":"The same pipeline as the `/v1/*` send, entered with a session instead of an API key: same pricing, same wallet reservation, same idempotency, same webhooks. `environment` is in the body because a session, unlike a key, does not state one — and it defaults to SANDBOX. A LIVE request passes the same decisions.md D5 gate as a client-created live key.","operationId":"DashboardSendController_sendSms","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection, exactly as on the /v1 send routes.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardSmsSendRequest"}}}},"responses":{"202":{"description":"Accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendAccepted"}}}},"402":{"description":"Insufficient wallet balance for this send."}},"security":[{"session":[]}],"summary":"Send one SMS as the signed-in user","tags":["Send (dashboard)"]}},"/send/email":{"post":{"description":"The same pipeline as the `/v1/*` send, entered with a session instead of an API key: same pricing, same wallet reservation, same idempotency, same webhooks. `environment` is in the body because a session, unlike a key, does not state one — and it defaults to SANDBOX. A LIVE request passes the same decisions.md D5 gate as a client-created live key.","operationId":"DashboardSendController_sendEmail","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection, exactly as on the /v1 send routes.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardEmailSendRequest"}}}},"responses":{"202":{"description":"Accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendAccepted"}}}},"402":{"description":"Insufficient wallet balance for this send."}},"security":[{"session":[]}],"summary":"Send one email as the signed-in user","tags":["Send (dashboard)"]}},"/send/sms/bulk":{"post":{"description":"The same pipeline as the `/v1/*` send, entered with a session instead of an API key: same pricing, same wallet reservation, same idempotency, same webhooks. `environment` is in the body because a session, unlike a key, does not state one — and it defaults to SANDBOX. A LIVE request passes the same decisions.md D5 gate as a client-created live key.","operationId":"DashboardSendController_sendSmsBulk","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection, exactly as on the /v1 send routes.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardSmsBulkSendRequest"}}}},"responses":{"202":{"description":"The whole batch was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendAccepted"}}}},"402":{"description":"Insufficient wallet balance for this send."}},"security":[{"session":[]}],"summary":"Bulk SMS as the signed-in user","tags":["Send (dashboard)"]}},"/send/email/bulk":{"post":{"description":"The same pipeline as the `/v1/*` send, entered with a session instead of an API key: same pricing, same wallet reservation, same idempotency, same webhooks. `environment` is in the body because a session, unlike a key, does not state one — and it defaults to SANDBOX. A LIVE request passes the same decisions.md D5 gate as a client-created live key.","operationId":"DashboardSendController_sendEmailBulk","parameters":[{"name":"idempotency-key","in":"header","description":"Replay protection, exactly as on the /v1 send routes.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardEmailBulkSendRequest"}}}},"responses":{"202":{"description":"The whole batch was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendAccepted"}}}},"402":{"description":"Insufficient wallet balance for this send."}},"security":[{"session":[]}],"summary":"Bulk email as the signed-in user","tags":["Send (dashboard)"]}},"/messages":{"get":{"description":"Keyset-paginated. Sandbox and live sends are both here, distinguished by `environment`.","operationId":"MessagesController_list","parameters":[{"name":"limit","required":false,"in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string","minLength":1}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]}},{"name":"channel","required":false,"in":"query","schema":{"type":"string","enum":["SMS","EMAIL"]}},{"name":"environment","required":false,"in":"query","schema":{"type":"string","enum":["SANDBOX","LIVE"]}}],"responses":{"200":{"description":"A page of messages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePage"}}}}},"security":[{"session":[]}],"summary":"Message log, newest first","tags":["Messages"]}},"/messages/scheduled":{"get":{"description":"Unpaginated and capped at 200, soonest first. Already-released messages are ordinary history and appear in the main log.","operationId":"MessagesController_listScheduled","parameters":[],"responses":{"200":{"description":"Cancellable scheduled messages.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledMessageList"}}}}},"security":[{"session":[]}],"summary":"Scheduled sends that have not fired","tags":["Messages"]}},"/messages/bulk-preview":{"post":{"description":"Creates nothing and reserves nothing. Bad rows and unpriced routes come back as data, not as a 400, because the caller is assembling a list.","operationId":"MessagesController_previewBulk","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendPreviewRequest"}}}},"responses":{"200":{"description":"Total cost, per-route breakdown and any problem rows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSendPreview"}}}}},"security":[{"session":[]}],"summary":"Price a recipient list without sending","tags":["Messages"]}},"/messages/{messageId}":{"get":{"operationId":"MessagesController_get","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"404":{"description":"No such message on this account."}},"security":[{"session":[]}],"summary":"One message","tags":["Messages"]}},"/messages/{messageId}/cancel":{"post":{"description":"Refunds the reservation. Losing the race against the sweep is a 409, not a silent success.","operationId":"MessagesController_cancelScheduled","parameters":[{"name":"messageId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The cancelled message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"404":{"description":"No such message on this account."},"409":{"description":"Already released to the queue, or not scheduled at all."}},"security":[{"session":[]}],"summary":"Cancel a scheduled message","tags":["Messages"]}},"/webhooks/endpoints":{"get":{"description":"Never includes signing secrets — those appear only at registration and rotation.","operationId":"WebhooksController_listEndpoints","parameters":[],"responses":{"200":{"description":"This account’s endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}}},"security":[{"session":[]}],"summary":"Registered endpoints","tags":["Webhooks"]},"post":{"description":"Returns the signing secret **once**. Verify deliveries with it per the `x-infitech-signature` scheme (HMAC-SHA-256 over `t.rawBody`). Omitting `events` subscribes to every event. https is required except on localhost.","operationId":"WebhooksController_createEndpoint","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"The endpoint, with its signing secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}}},"409":{"description":"This account already has an endpoint on that URL."}},"security":[{"session":[]}],"summary":"Register an endpoint","tags":["Webhooks"]}},"/webhooks/endpoints/{endpointId}":{"get":{"operationId":"WebhooksController_getEndpoint","parameters":[{"name":"endpointId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"404":{"description":"No such endpoint on this account."}},"security":[{"session":[]}],"summary":"One endpoint","tags":["Webhooks"]},"patch":{"description":"Set `status` to DISABLED to stop delivery while keeping the attempt log.","operationId":"WebhooksController_updateEndpoint","parameters":[{"name":"endpointId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointUpdate"}}}},"responses":{"200":{"description":"The updated endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"404":{"description":"No such endpoint on this account."},"409":{"description":"Another of this account’s endpoints already uses that URL."}},"security":[{"session":[]}],"summary":"Edit an endpoint","tags":["Webhooks"]},"delete":{"description":"Takes its attempt log with it. Disable instead if you want to keep the history.","operationId":"WebhooksController_removeEndpoint","parameters":[{"name":"endpointId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The deleted endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"404":{"description":"No such endpoint on this account."}},"security":[{"session":[]}],"summary":"Delete an endpoint","tags":["Webhooks"]}},"/webhooks/endpoints/{endpointId}/rotate-secret":{"post":{"description":"Immediate cutover — the previous secret stops verifying as soon as this returns. Deploy your handler’s new secret before calling it, not after.","operationId":"WebhooksController_rotateEndpointSecret","parameters":[{"name":"endpointId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The endpoint, with its new secret shown once.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointWithSecret"}}}},"404":{"description":"No such endpoint on this account."}},"security":[{"session":[]}],"summary":"Mint a new signing secret","tags":["Webhooks"]}},"/webhooks/deliveries":{"get":{"description":"One row per attempt, not per event: a delivery that exhausted the five-attempt ladder (decisions.md D11) appears five times, the first four PENDING and the last FAILED.","operationId":"WebhooksController_listDeliveries","parameters":[{"name":"limit","required":false,"in":"query","schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","required":false,"in":"query","schema":{"type":"string","minLength":1}},{"name":"webhookEndpointId","required":false,"in":"query","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"messageId","required":false,"in":"query","schema":{"type":"string","minLength":1,"maxLength":64}},{"name":"status","required":false,"in":"query","schema":{"type":"string","enum":["PENDING","DELIVERED","FAILED"]}}],"responses":{"200":{"description":"A page of attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryPage"}}}}},"security":[{"session":[]}],"summary":"Delivery attempts, newest first","tags":["Webhooks"]}},"/webhooks/deliveries/{deliveryId}":{"get":{"operationId":"WebhooksController_getDelivery","parameters":[{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The attempt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"404":{"description":"No such delivery on this account."}},"security":[{"session":[]}],"summary":"One attempt, with the payload sent and the response received","tags":["Webhooks"]}},"/webhooks/deliveries/{deliveryId}/resend":{"post":{"description":"Queues a fresh five-attempt ladder with the original payload byte-for-byte (same `occurredAt`) under a new signature timestamp. Works on a delivered attempt as readily as a failed one. The original rows are never modified; the replay appears as new ones.","operationId":"WebhooksController_resendDelivery","parameters":[{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":"The replay is queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResendAccepted"}}}},"404":{"description":"No such delivery on this account."},"409":{"description":"The endpoint is disabled; re-enable it before resending."},"422":{"description":"The stored payload predates a shape change and cannot be replayed."}},"security":[{"session":[]}],"summary":"Replay a logged delivery","tags":["Webhooks"]}},"/admin/revenue":{"get":{"description":"Top-ups, client charge and provider cost bucketed by day, week or month, plus the highest-revenue accounts in the window. Live traffic only. Compare `costedMessageCount` with `messageCount` before trusting the margin: the difference is traffic whose provider cost is unknown or not in MWK.","operationId":"RevenueController_report","parameters":[{"name":"granularity","required":false,"in":"query","schema":{"default":"MONTH","type":"string","enum":["DAY","WEEK","MONTH"]}},{"name":"periods","required":false,"in":"query","schema":{"default":6,"type":"integer","minimum":1,"maximum":24}},{"name":"accountLimit","required":false,"in":"query","schema":{"default":10,"type":"integer","minimum":1,"maximum":50}}],"responses":{"200":{"description":"The report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRevenueReport"}}}},"403":{"description":"SUPER_ADMIN only."}},"security":[{"session":[]}],"summary":"Revenue, provider cost and margin","tags":["Admin — revenue"]}},"/health":{"get":{"description":"No authentication. Does not touch Postgres or Redis.","operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":"The process is up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}},"summary":"Liveness probe","tags":["Health"]}}},"info":{"title":"InfiSend","description":"InfiSend — SMS via Africa's Talking and email via SMTP behind one API,\nbilled per message from a prepaid MWK wallet.\n\n## Authentication\n\nTwo schemes, and which one an endpoint takes is part of its contract:\n\n- **session** — a dashboard JWT, `Authorization: Bearer <token>` from\n  `POST /auth/login`. Used by everything that *administers* an account: wallet,\n  API keys, templates, KYC, webhooks, message logs.\n- **apiKey** — an API key, `Authorization: Bearer sk_live_…` or `sk_test_…`.\n  Used by the `/v1/*` machine surface, which is send-only. Keys are scoped\n  (SMS / EMAIL / READ_ONLY) and rate-limited per key.\n\nA key cannot manage the account and a session cannot be handed to a server-side\nintegration: a leaked send credential must not be able to mint itself a live key or\nrepoint a webhook.\n\n## Environments\n\nEvery key is either `SANDBOX` or `LIVE`. Sandbox mirrors live behaviour exactly —\nsame status transitions, same webhook payloads, simulated delays and failures — and\nnever charges the wallet or reaches a provider.\n\n## Money\n\nAmounts are decimal **strings** in MWK, never JSON numbers. A float in a wallet balance\nis not recoverable after the fact, so the wire format refuses to carry one.\n\n## Sending is asynchronous\n\nA send returns `202` with a `messageId` once the message is written and the wallet\ncredit reserved. The outcome arrives on your registered webhook\n(`POST /webhooks/endpoints`), signed with `x-infitech-signature`. There is no\npolling endpoint by design.","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"https://infisend-api.infi-tech.cloud"}],"components":{"securitySchemes":{"session":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Dashboard session token from POST /auth/login."},"apiKey":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"An API key: sk_live_… or sk_test_…. Send-only, scoped, rate-limited."}},"schemas":{"AdminAccountList":{"type":"object","properties":{"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"status":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]},"ownerEmail":{"type":"string"},"walletBalance":{},"totalSpendMtd":{},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","status","ownerEmail","walletBalance","totalSpendMtd","createdAt"],"additionalProperties":false}},"total":{"type":"integer","minimum":0,"maximum":9007199254740991},"page":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991},"pageSize":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991}},"required":["accounts","total","page","pageSize"],"additionalProperties":false},"AdminAccountDetail":{"type":"object","properties":{"account":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"ownerUserId":{"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","ownerUserId","status","createdAt"],"additionalProperties":false},"ownerEmail":{"type":"string"},"wallet":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"balance":{},"minLiveBalance":{}},"required":["id","accountId","balance","minLiveBalance"],"additionalProperties":false},"kycHistory":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"type":{"type":"string","enum":["INDIVIDUAL","BUSINESS"]},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"submittedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reviewedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reviewerEmail":{"nullable":true,"type":"string"},"rejectionReason":{"nullable":true,"type":"string"}},"required":["id","type","status","submittedAt","reviewedAt","reviewerEmail","rejectionReason"],"additionalProperties":false}},"apiKeys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"keyPrefix":{"type":"string"},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","environment","status","keyPrefix","lastUsedAt"],"additionalProperties":false}},"recentMessages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"to":{"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","channel","status","to","createdAt"],"additionalProperties":false}}},"required":["account","ownerEmail","wallet","kycHistory","apiKeys","recentMessages"],"additionalProperties":false},"AdminAccountStatusChange":{"type":"object","properties":{"reason":{"type":"string","minLength":5,"maxLength":1000}},"required":["reason"],"additionalProperties":false},"WalletSummary":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"balance":{},"minLiveBalance":{},"meetsLiveThreshold":{"type":"boolean"}},"required":["id","accountId","balance","minLiveBalance","meetsLiveThreshold"],"additionalProperties":false},"MinLiveBalanceUpdate":{"type":"object","properties":{"minLiveBalance":{"anyOf":[{"type":"string"},{"type":"number"}]},"note":{"type":"string","minLength":5,"maxLength":1000}},"required":["minLiveBalance","note"],"additionalProperties":false},"WalletAdjustRequest":{"type":"object","properties":{"amount":{"anyOf":[{"type":"string"},{"type":"number"}]},"note":{"type":"string","minLength":5,"maxLength":1000}},"required":["amount","note"],"additionalProperties":false},"LiveKeyEligibility":{"type":"object","properties":{"accountId":{"type":"string","minLength":1,"maxLength":64},"accountStatus":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]},"balance":{},"minLiveBalance":{},"eligible":{"type":"boolean"},"reason":{"nullable":true,"type":"string"}},"required":["accountId","accountStatus","balance","minLiveBalance","eligible","reason"],"additionalProperties":false},"WalletTransactionPage":{"type":"object","properties":{"transactions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"walletId":{"type":"string","minLength":1,"maxLength":64},"type":{"type":"string","enum":["TOPUP","DEBIT","REFUND","ADJUSTMENT"]},"amount":{},"balanceAfter":{},"referenceType":{"nullable":true,"type":"string"},"referenceId":{"nullable":true,"type":"string"},"paymentProvider":{"nullable":true,"type":"string","enum":["PAYCHANGU","INFI_PAY","MANUAL"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","walletId","type","amount","balanceAfter","referenceType","referenceId","paymentProvider","createdAt"],"additionalProperties":false}},"nextCursor":{"nullable":true,"type":"string"}},"required":["transactions","nextCursor"],"additionalProperties":false},"ApiKeyList":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","name","keyPrefix","environment","scopes","status","lastUsedAt","createdAt"],"additionalProperties":false}}},"required":["keys"],"additionalProperties":false},"ApiKeyCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}}},"required":["name","environment","scopes"],"additionalProperties":false},"ApiKeyWithSecret":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"secret":{"type":"string"}},"required":["id","accountId","name","keyPrefix","environment","scopes","status","lastUsedAt","createdAt","secret"],"additionalProperties":false},"ApiKeyRotate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scopes":{"minItems":1,"maxItems":3,"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}}},"additionalProperties":false},"ApiKeyRotation":{"type":"object","properties":{"created":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"secret":{"type":"string"}},"required":["id","accountId","name","keyPrefix","environment","scopes","status","lastUsedAt","createdAt","secret"],"additionalProperties":false},"replaced":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","name","keyPrefix","environment","scopes","status","lastUsedAt","createdAt"],"additionalProperties":false}},"required":["created","replaced"],"additionalProperties":false},"ApiKey":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"status":{"type":"string","enum":["ACTIVE","REVOKED"]},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","name","keyPrefix","environment","scopes","status","lastUsedAt","createdAt"],"additionalProperties":false},"ApiKeyIdentity":{"type":"object","properties":{"accountId":{"type":"string","minLength":1,"maxLength":64},"accountName":{"type":"string"},"apiKeyId":{"type":"string","minLength":1,"maxLength":64},"keyPrefix":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scopes":{"type":"array","items":{"type":"string","enum":["SMS","EMAIL","READ_ONLY"]}},"lastUsedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["accountId","accountName","apiKeyId","keyPrefix","environment","scopes","lastUsedAt"],"additionalProperties":false},"AdminAuditLogPage":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"actorUserId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"actorEmail":{"nullable":true,"type":"string"},"action":{"type":"string"},"targetType":{"type":"string"},"targetId":{"type":"string"},"metadata":{},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","actorUserId","actorEmail","action","targetType","targetId","metadata","createdAt"],"additionalProperties":false}},"total":{"type":"integer","minimum":0,"maximum":9007199254740991},"page":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991},"pageSize":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991}},"required":["entries","total","page","pageSize"],"additionalProperties":false},"SignupRequest":{"type":"object","properties":{"accountName":{"type":"string","minLength":2,"maxLength":120},"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"password":{"type":"string","minLength":8}},"required":["accountName","email","password"],"additionalProperties":false},"AuthSession":{"type":"object","properties":{"accessToken":{"type":"string"},"expiresIn":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"user":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"email":{"type":"string"},"role":{"type":"string","enum":["SUPER_ADMIN","CLIENT"]},"accountId":{"type":"string","minLength":1,"maxLength":64},"isVerified":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","email","role","accountId","isVerified","createdAt"],"additionalProperties":false},"account":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"ownerUserId":{"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","name","ownerUserId","status","createdAt"],"additionalProperties":false}},"required":["accessToken","expiresIn","user","account"],"additionalProperties":false},"LoginRequest":{"type":"object","properties":{"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"password":{"type":"string","minLength":1}},"required":["email","password"],"additionalProperties":false},"PasswordResetRequest":{"type":"object","properties":{"email":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["email"],"additionalProperties":false},"PasswordResetAcknowledgement":{"type":"object","properties":{"accepted":{"type":"boolean","enum":[true]}},"required":["accepted"],"additionalProperties":false},"PasswordResetConfirm":{"type":"object","properties":{"token":{"type":"string","minLength":1,"maxLength":200},"password":{"type":"string","minLength":8}},"required":["token","password"],"additionalProperties":false},"AuthenticatedUser":{"type":"object","properties":{"userId":{"type":"string","minLength":1,"maxLength":64},"email":{"type":"string"},"role":{"type":"string","enum":["SUPER_ADMIN","CLIENT"]},"accountId":{"type":"string","minLength":1,"maxLength":64},"accountStatus":{"type":"string","enum":["PENDING_KYC","ACTIVE","SUSPENDED"]}},"required":["userId","email","role","accountId","accountStatus"],"additionalProperties":false},"AdminProviderConfigList":{"type":"object","properties":{"providers":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","enum":["AFRICAS_TALKING","SMTP","INFI_PAY"]},"name":{"type":"string"},"role":{"type":"string"},"consumedBy":{"type":"string","enum":["API","WORKER"]},"fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"isSecret":{"type":"boolean"},"preview":{"nullable":true,"type":"string"},"source":{"type":"string","enum":["STORED","ENVIRONMENT","UNSET"]},"updatedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedByEmail":{"nullable":true,"type":"string"}},"required":["key","label","isSecret","preview","source","updatedAt","updatedByEmail"],"additionalProperties":false}}},"required":["provider","name","role","consumedBy","fields"],"additionalProperties":false}}},"required":["providers"],"additionalProperties":false},"AdminProviderCredentialUpdate":{"type":"object","properties":{"value":{"type":"string","minLength":1,"maxLength":4096},"reason":{"type":"string","minLength":5,"maxLength":1000}},"required":["value","reason"],"additionalProperties":false},"AdminProviderCredentialDelete":{"type":"object","properties":{"reason":{"type":"string","minLength":5,"maxLength":1000}},"required":["reason"],"additionalProperties":false},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"service":{"type":"string"},"version":{"type":"string"},"uptimeSeconds":{"type":"number","minimum":0},"correlationId":{"type":"string"}},"required":["status","service","version","uptimeSeconds","correlationId"],"additionalProperties":false},"KycSubmissionSummaryList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"type":{"type":"string","enum":["INDIVIDUAL","BUSINESS"]},"idDocumentUrl":{"type":"string"},"businessRegDocumentUrl":{"nullable":true,"type":"string"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"submittedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reviewedByUserId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"reviewedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"rejectionReason":{"nullable":true,"type":"string"},"accountName":{"type":"string"}},"required":["id","accountId","type","idDocumentUrl","businessRegDocumentUrl","status","submittedAt","reviewedByUserId","reviewedAt","rejectionReason","accountName"],"additionalProperties":false}},"KycSubmissionForReview":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"type":{"type":"string","enum":["INDIVIDUAL","BUSINESS"]},"idDocumentUrl":{"type":"string"},"businessRegDocumentUrl":{"nullable":true,"type":"string"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"submittedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reviewedByUserId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"reviewedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"rejectionReason":{"nullable":true,"type":"string"},"accountName":{"type":"string"},"documents":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["ID","BUSINESS_REGISTRATION"]},"objectKey":{"type":"string"},"downloadUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["kind","objectKey","downloadUrl","expiresAt"],"additionalProperties":false}}},"required":["id","accountId","type","idDocumentUrl","businessRegDocumentUrl","status","submittedAt","reviewedByUserId","reviewedAt","rejectionReason","accountName","documents"],"additionalProperties":false},"KycApprovalRequest":{"type":"object","properties":{"note":{"type":"string","maxLength":1000}},"additionalProperties":false},"KycSubmissionSummary":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"type":{"type":"string","enum":["INDIVIDUAL","BUSINESS"]},"idDocumentUrl":{"type":"string"},"businessRegDocumentUrl":{"nullable":true,"type":"string"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"submittedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reviewedByUserId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"reviewedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"rejectionReason":{"nullable":true,"type":"string"},"accountName":{"type":"string"}},"required":["id","accountId","type","idDocumentUrl","businessRegDocumentUrl","status","submittedAt","reviewedByUserId","reviewedAt","rejectionReason","accountName"],"additionalProperties":false},"KycRejectionRequest":{"type":"object","properties":{"reason":{"type":"string","minLength":10,"maxLength":1000}},"required":["reason"],"additionalProperties":false},"KycUploadTargetRequest":{"type":"object","properties":{"kind":{"type":"string","enum":["ID","BUSINESS_REGISTRATION"]},"contentType":{"type":"string","enum":["application/pdf","image/jpeg","image/png"]}},"required":["kind","contentType"],"additionalProperties":false},"KycUploadTarget":{"type":"object","properties":{"uploadUrl":{"type":"string","format":"uri"},"formFields":{"type":"object","additionalProperties":{"type":"string"}},"objectKey":{"type":"string","minLength":1,"maxLength":512,"pattern":"^kyc\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-]+\\.[A-Za-z0-9]+$"},"maxBytes":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["uploadUrl","formFields","objectKey","maxBytes","expiresAt"],"additionalProperties":false},"KycSubmissionRequest":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["INDIVIDUAL"]},"idDocumentKey":{"type":"string","minLength":1,"maxLength":512,"pattern":"^kyc\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-]+\\.[A-Za-z0-9]+$"}},"required":["type","idDocumentKey"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["BUSINESS"]},"idDocumentKey":{"type":"string","minLength":1,"maxLength":512,"pattern":"^kyc\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-]+\\.[A-Za-z0-9]+$"},"businessRegDocumentKey":{"type":"string","minLength":1,"maxLength":512,"pattern":"^kyc\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-]+\\.[A-Za-z0-9]+$"}},"required":["type","idDocumentKey","businessRegDocumentKey"],"additionalProperties":false}]},"PricingRuleList":{"type":"object","properties":{"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"route":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"specificity":{"type":"string","enum":["NETWORK","COUNTRY","CHANNEL"]},"unitCost":{},"effectiveFrom":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdByUserId":{"type":"string","minLength":1,"maxLength":64},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"type":"string","enum":["EFFECTIVE","SCHEDULED","SUPERSEDED"]}},"required":["id","route","specificity","unitCost","effectiveFrom","createdByUserId","createdAt","status"],"additionalProperties":false}}},"required":["rules"],"additionalProperties":false},"PricingCoverageList":{"type":"object","properties":{"coverage":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"hasFallback":{"type":"boolean"},"fallbackUnitCost":{"nullable":true},"covered":{"type":"array","items":{"type":"object","properties":{"ruleId":{"type":"string","minLength":1,"maxLength":64},"route":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"specificity":{"type":"string","enum":["NETWORK","COUNTRY","CHANNEL"]},"unitCost":{},"effectiveFrom":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["ruleId","route","specificity","unitCost","effectiveFrom"],"additionalProperties":false}},"gap":{"nullable":true,"type":"string"}},"required":["channel","hasFallback","fallbackUnitCost","covered","gap"],"additionalProperties":false}}},"required":["coverage"],"additionalProperties":false},"PriceResolution":{"oneOf":[{"type":"object","properties":{"priced":{"type":"boolean","enum":[true]},"route":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"unitCost":{},"ruleId":{"type":"string","minLength":1,"maxLength":64},"matched":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"specificity":{"type":"string","enum":["NETWORK","COUNTRY","CHANNEL"]},"effectiveFrom":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"resolvedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["priced","route","unitCost","ruleId","matched","specificity","effectiveFrom","resolvedAt"],"additionalProperties":false},{"type":"object","properties":{"priced":{"type":"boolean","enum":[false]},"route":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"resolvedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"reason":{"type":"string"}},"required":["priced","route","resolvedAt","reason"],"additionalProperties":false}]},"PricingRuleCreate":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"default":null,"nullable":true,"type":"string","pattern":"^[A-Z]{2}$"},"network":{"default":null,"nullable":true,"type":"string","maxLength":40,"pattern":"^[A-Z0-9]+(?:_[A-Z0-9]+)*$"},"unitCost":{"anyOf":[{"type":"string"},{"type":"number"}]},"effectiveFrom":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["channel","unitCost"],"additionalProperties":false},"PricingRuleSummary":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"route":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"country":{"nullable":true,"type":"string"},"network":{"nullable":true,"type":"string"}},"required":["channel","country","network"],"additionalProperties":false},"specificity":{"type":"string","enum":["NETWORK","COUNTRY","CHANNEL"]},"unitCost":{},"effectiveFrom":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdByUserId":{"type":"string","minLength":1,"maxLength":64},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"status":{"type":"string","enum":["EFFECTIVE","SCHEDULED","SUPERSEDED"]}},"required":["id","route","specificity","unitCost","effectiveFrom","createdByUserId","createdAt","status"],"additionalProperties":false},"TemplateList":{"type":"object","properties":{"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"channel":{"type":"string","enum":["SMS","EMAIL"]},"subject":{"nullable":true,"type":"string"},"body":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","name","channel","subject","body","variables","createdAt","updatedAt"],"additionalProperties":false}}},"required":["templates"],"additionalProperties":false},"Template":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"name":{"type":"string"},"channel":{"type":"string","enum":["SMS","EMAIL"]},"subject":{"nullable":true,"type":"string"},"body":{"type":"string"},"variables":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","name","channel","subject","body","variables","createdAt","updatedAt"],"additionalProperties":false},"TemplateCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"channel":{"type":"string","enum":["SMS","EMAIL"]},"subject":{"type":"string","minLength":1,"maxLength":255},"body":{"type":"string","minLength":1,"maxLength":500000}},"required":["name","channel","body"]},"TemplateUpdate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"subject":{"type":"string","minLength":1,"maxLength":255},"body":{"type":"string","minLength":1,"maxLength":500000}}},"SuppressionList":{"type":"object","properties":{"suppressions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"destination":{"type":"string"},"reason":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]},"evidence":{"nullable":true,"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","channel","destination","reason","evidence","createdAt"],"additionalProperties":false}},"nextCursor":{"nullable":true,"type":"string"}},"required":["suppressions","nextCursor"],"additionalProperties":false},"SuppressionCreate":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"destination":{"type":"string","minLength":1,"maxLength":320},"reason":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]},"evidence":{"type":"string","maxLength":500}},"required":["channel","destination","reason"]},"Suppression":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"destination":{"type":"string"},"reason":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]},"evidence":{"nullable":true,"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","channel","destination","reason","evidence","createdAt"],"additionalProperties":false},"SmsSendRequest":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},"message":{"type":"string","minLength":1,"maxLength":10000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"senderId":{"type":"string","minLength":3,"maxLength":11,"pattern":"^[A-Za-z0-9][A-Za-z0-9 _-]*$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"type":"string","minLength":8,"maxLength":255}},"required":["to"]},"SendAccepted":{"type":"object","properties":{"messageId":{"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"channel":{"type":"string","enum":["SMS","EMAIL"]},"to":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"estimatedCost":{},"duplicate":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["messageId","status","channel","to","environment","estimatedCost","duplicate","createdAt"],"additionalProperties":false},"EmailSendRequest":{"type":"object","properties":{"to":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"subject":{"type":"string","minLength":1,"maxLength":255},"text":{"type":"string","minLength":1,"maxLength":200000},"html":{"type":"string","minLength":1,"maxLength":500000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"replyTo":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"fromName":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[^\\r\\n]+$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"type":"string","minLength":8,"maxLength":255}},"required":["to"]},"SmsBulkSendRequest":{"type":"object","properties":{"recipients":{"minItems":1,"type":"array","items":{"anyOf":[{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["to"]}]}},"recipientsCsv":{"type":"string","minLength":1,"maxLength":2000000},"message":{"type":"string","minLength":1,"maxLength":10000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"senderId":{"type":"string","minLength":3,"maxLength":11,"pattern":"^[A-Za-z0-9][A-Za-z0-9 _-]*$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}}},"BulkSendAccepted":{"type":"object","properties":{"batchSize":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalCost":{},"channel":{"type":"string","enum":["SMS","EMAIL"]},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scheduledFor":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"messages":{"type":"array","items":{"type":"object","properties":{"messageId":{"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"channel":{"type":"string","enum":["SMS","EMAIL"]},"to":{"type":"string"},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"estimatedCost":{},"duplicate":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["messageId","status","channel","to","environment","estimatedCost","duplicate","createdAt"],"additionalProperties":false}},"suppressedRecipients":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"reason":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]},"suppressedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["recipient","reason","suppressedAt"],"additionalProperties":false}}},"required":["batchSize","totalCost","channel","environment","scheduledFor","messages","suppressedRecipients"],"additionalProperties":false},"EmailBulkSendRequest":{"type":"object","properties":{"recipients":{"minItems":1,"type":"array","items":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"object","properties":{"to":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["to"]}]}},"recipientsCsv":{"type":"string","minLength":1,"maxLength":2000000},"subject":{"type":"string","minLength":1,"maxLength":255},"text":{"type":"string","minLength":1,"maxLength":200000},"html":{"type":"string","minLength":1,"maxLength":500000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"replyTo":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"fromName":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[^\\r\\n]+$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}}},"Message":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"apiKeyId":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"direction":{"type":"string","enum":["OUTBOUND"]},"to":{"type":"string"},"from":{"type":"string"},"subject":{"nullable":true,"type":"string"},"body":{"nullable":true,"type":"string"},"templateId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"providerMessageId":{"nullable":true,"type":"string"},"costCharged":{"nullable":true},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scheduledFor":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"nullable":true,"type":"string"},"failureCode":{"nullable":true,"type":"string"},"failureReason":{"nullable":true,"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"sentAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"deliveredAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","apiKeyId","channel","direction","to","from","subject","body","templateId","status","providerMessageId","costCharged","environment","scheduledFor","idempotencyKey","failureCode","failureReason","createdAt","sentAt","deliveredAt"],"additionalProperties":false},"DashboardSmsSendRequest":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},"message":{"type":"string","minLength":1,"maxLength":10000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"senderId":{"type":"string","minLength":3,"maxLength":11,"pattern":"^[A-Za-z0-9][A-Za-z0-9 _-]*$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"type":"string","minLength":8,"maxLength":255},"environment":{"default":"SANDBOX","type":"string","enum":["SANDBOX","LIVE"]}},"required":["to"]},"DashboardEmailSendRequest":{"type":"object","properties":{"to":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"subject":{"type":"string","minLength":1,"maxLength":255},"text":{"type":"string","minLength":1,"maxLength":200000},"html":{"type":"string","minLength":1,"maxLength":500000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"replyTo":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"fromName":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[^\\r\\n]+$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"type":"string","minLength":8,"maxLength":255},"environment":{"default":"SANDBOX","type":"string","enum":["SANDBOX","LIVE"]}},"required":["to"]},"DashboardSmsBulkSendRequest":{"type":"object","properties":{"recipients":{"minItems":1,"type":"array","items":{"anyOf":[{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{7,14}$"},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["to"]}]}},"recipientsCsv":{"type":"string","minLength":1,"maxLength":2000000},"message":{"type":"string","minLength":1,"maxLength":10000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"senderId":{"type":"string","minLength":3,"maxLength":11,"pattern":"^[A-Za-z0-9][A-Za-z0-9 _-]*$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"environment":{"default":"SANDBOX","type":"string","enum":["SANDBOX","LIVE"]}}},"DashboardEmailBulkSendRequest":{"type":"object","properties":{"recipients":{"minItems":1,"type":"array","items":{"anyOf":[{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},{"type":"object","properties":{"to":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["to"]}]}},"recipientsCsv":{"type":"string","minLength":1,"maxLength":2000000},"subject":{"type":"string","minLength":1,"maxLength":255},"text":{"type":"string","minLength":1,"maxLength":200000},"html":{"type":"string","minLength":1,"maxLength":500000},"templateId":{"type":"string","minLength":1,"maxLength":64},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}},"replyTo":{"type":"string","maxLength":320,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"fromName":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[^\\r\\n]+$"},"scheduledFor":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"environment":{"default":"SANDBOX","type":"string","enum":["SANDBOX","LIVE"]}}},"MessagePage":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"apiKeyId":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"direction":{"type":"string","enum":["OUTBOUND"]},"to":{"type":"string"},"from":{"type":"string"},"subject":{"nullable":true,"type":"string"},"body":{"nullable":true,"type":"string"},"templateId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"providerMessageId":{"nullable":true,"type":"string"},"costCharged":{"nullable":true},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scheduledFor":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"nullable":true,"type":"string"},"failureCode":{"nullable":true,"type":"string"},"failureReason":{"nullable":true,"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"sentAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"deliveredAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","apiKeyId","channel","direction","to","from","subject","body","templateId","status","providerMessageId","costCharged","environment","scheduledFor","idempotencyKey","failureCode","failureReason","createdAt","sentAt","deliveredAt"],"additionalProperties":false}},"nextCursor":{"nullable":true,"type":"string"}},"required":["messages","nextCursor"],"additionalProperties":false},"ScheduledMessageList":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"apiKeyId":{"type":"string","minLength":1,"maxLength":64},"channel":{"type":"string","enum":["SMS","EMAIL"]},"direction":{"type":"string","enum":["OUTBOUND"]},"to":{"type":"string"},"from":{"type":"string"},"subject":{"nullable":true,"type":"string"},"body":{"nullable":true,"type":"string"},"templateId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"status":{"type":"string","enum":["QUEUED","SENT","DELIVERED","FAILED","REJECTED","CANCELLED"]},"providerMessageId":{"nullable":true,"type":"string"},"costCharged":{"nullable":true},"environment":{"type":"string","enum":["SANDBOX","LIVE"]},"scheduledFor":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"idempotencyKey":{"nullable":true,"type":"string"},"failureCode":{"nullable":true,"type":"string"},"failureReason":{"nullable":true,"type":"string"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"sentAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"deliveredAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","apiKeyId","channel","direction","to","from","subject","body","templateId","status","providerMessageId","costCharged","environment","scheduledFor","idempotencyKey","failureCode","failureReason","createdAt","sentAt","deliveredAt"],"additionalProperties":false}}},"required":["messages"],"additionalProperties":false},"BulkSendPreviewRequest":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"recipients":{"minItems":1,"type":"array","items":{"anyOf":[{"type":"string","minLength":1,"maxLength":320},{"type":"object","properties":{"to":{"type":"string","minLength":1,"maxLength":320},"variables":{"type":"object","additionalProperties":{"type":"string","maxLength":2000}}},"required":["to"]}]}},"recipientsCsv":{"type":"string","minLength":1,"maxLength":2000000}},"required":["channel"]},"BulkSendPreview":{"type":"object","properties":{"channel":{"type":"string","enum":["SMS","EMAIL"]},"recipientCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalCost":{},"balance":{},"sufficientBalance":{"type":"boolean"},"invalidRecipients":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"reason":{"type":"string"}},"required":["recipient","reason"],"additionalProperties":false}},"unpricedRoutes":{"type":"array","items":{"type":"object","properties":{"route":{"type":"string"},"reason":{"type":"string"}},"required":["route","reason"],"additionalProperties":false}},"suppressedRecipients":{"type":"array","items":{"type":"object","properties":{"recipient":{"type":"string"},"reason":{"type":"string","enum":["USER_STOP","USER_UNSUBSCRIBE","PROVIDER_REPORTED"]},"suppressedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["recipient","reason","suppressedAt"],"additionalProperties":false}}},"required":["channel","recipientCount","totalCost","balance","sufficientBalance","invalidRecipients","unpricedRoutes","suppressedRecipients"],"additionalProperties":false},"TopupRequest":{"type":"object","properties":{"amount":{"anyOf":[{"type":"string"},{"type":"number"}]},"provider":{"type":"string","enum":["AIRTEL","MPAMBA"]},"phoneNumber":{"type":"string"}},"required":["amount","provider","phoneNumber"],"additionalProperties":false},"TopupInitiation":{"type":"object","properties":{"reference":{"type":"string"},"provider":{"type":"string","enum":["AIRTEL","MPAMBA"]},"phoneNumber":{"type":"string"},"amount":{},"status":{"type":"string","enum":["PENDING","SUCCESSFUL","FAILED"]}},"required":["reference","provider","phoneNumber","amount","status"],"additionalProperties":false},"TopupStatusResult":{"type":"object","properties":{"reference":{"type":"string"},"status":{"type":"string","enum":["PENDING","SUCCESSFUL","FAILED"]},"amount":{"nullable":true},"creditedAmount":{"nullable":true},"updatedAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["reference","status","amount","creditedAmount","updatedAt"],"additionalProperties":false},"AdminRevenueReport":{"type":"object","properties":{"granularity":{"type":"string","enum":["DAY","WEEK","MONTH"]},"from":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"to":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"totals":{"type":"object","properties":{"topUps":{},"clientCharge":{},"providerCost":{},"grossMargin":{},"marginPercent":{"nullable":true,"type":"string"},"messageCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"costedMessageCount":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["topUps","clientCharge","providerCost","grossMargin","marginPercent","messageCount","costedMessageCount"],"additionalProperties":false},"periods":{"type":"array","items":{"type":"object","properties":{"topUps":{},"clientCharge":{},"providerCost":{},"grossMargin":{},"marginPercent":{"nullable":true,"type":"string"},"messageCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"costedMessageCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"start":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"end":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"label":{"type":"string"}},"required":["topUps","clientCharge","providerCost","grossMargin","marginPercent","messageCount","costedMessageCount","start","end","label"],"additionalProperties":false}},"topAccounts":{"type":"array","items":{"type":"object","properties":{"topUps":{},"clientCharge":{},"providerCost":{},"grossMargin":{},"marginPercent":{"nullable":true,"type":"string"},"messageCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"costedMessageCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"accountId":{"type":"string","minLength":1,"maxLength":64},"accountName":{"type":"string"}},"required":["topUps","clientCharge","providerCost","grossMargin","marginPercent","messageCount","costedMessageCount","accountId","accountName"],"additionalProperties":false}}},"required":["granularity","from","to","totals","periods","topAccounts"],"additionalProperties":false},"WebhookEndpointList":{"type":"object","properties":{"endpoints":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","url","events","status","createdAt","updatedAt"],"additionalProperties":false}}},"required":["endpoints"],"additionalProperties":false},"WebhookEndpointCreate":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"default":[],"maxItems":6,"type":"array","items":{"type":"string","enum":["message.queued","message.sent","message.delivered","message.failed","message.rejected","message.cancelled"]}}},"required":["url"]},"WebhookEndpointWithSecret":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"secret":{"type":"string"}},"required":["id","accountId","url","events","status","createdAt","updatedAt","secret"],"additionalProperties":false},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"accountId":{"type":"string","minLength":1,"maxLength":64},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"updatedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","accountId","url","events","status","createdAt","updatedAt"],"additionalProperties":false},"WebhookEndpointUpdate":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"events":{"maxItems":6,"type":"array","items":{"type":"string","enum":["message.queued","message.sent","message.delivered","message.failed","message.rejected","message.cancelled"]}},"status":{"type":"string","enum":["ACTIVE","DISABLED"]}}},"WebhookDeliveryPage":{"type":"object","properties":{"deliveries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"webhookEndpointId":{"type":"string","minLength":1,"maxLength":64},"messageId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"payload":{},"responseStatus":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"responseBody":{"nullable":true,"type":"string"},"attempt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["PENDING","DELIVERED","FAILED"]},"nextAttemptAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","webhookEndpointId","messageId","payload","responseStatus","responseBody","attempt","status","nextAttemptAt","createdAt"],"additionalProperties":false}},"nextCursor":{"nullable":true,"type":"string"}},"required":["deliveries","nextCursor"],"additionalProperties":false},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":64},"webhookEndpointId":{"type":"string","minLength":1,"maxLength":64},"messageId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"payload":{},"responseStatus":{"nullable":true,"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"responseBody":{"nullable":true,"type":"string"},"attempt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"status":{"type":"string","enum":["PENDING","DELIVERED","FAILED"]},"nextAttemptAt":{"nullable":true,"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"createdAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"}},"required":["id","webhookEndpointId","messageId","payload","responseStatus","responseBody","attempt","status","nextAttemptAt","createdAt"],"additionalProperties":false},"WebhookResendAccepted":{"type":"object","properties":{"webhookEndpointId":{"type":"string","minLength":1,"maxLength":64},"messageId":{"nullable":true,"type":"string","minLength":1,"maxLength":64},"event":{"type":"string"},"maxAttempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["webhookEndpointId","messageId","event","maxAttempts"],"additionalProperties":false}}}}