Skip to main content
Project-scoped endpoints under /platform/v1/whatsapp, authenticated with your X-API-Key. IDs in these paths are Meta WABA and Business Portfolio IDs, not Kapso UUIDs. Reads use persisted evidence and never make a synchronous Meta request. IDs that are unknown or not visible to your project return 404, and a portfolio read includes only the accounts your project can see.

Funding status

  • funded — funding is verified, the allocation is approved and observed funding IDs match.
  • pending — an initial funding operation is in progress.
  • unknown — previously verified, but current evidence cannot confirm funding.
  • not_funded — funding was never verified, including an attempt retired because the customer kept their existing Meta payment method.
  • revoked — Meta allocation evidence confirms the funding was deleted. Retiring an unsuccessful attempt locally does not mean Meta funding was revoked.
currency is the Kapso settlement currency; waba_currency is the funding snapshot, or the observed WABA currency when there is no attachment. last_verified_at is the latest recorded transition into verification. last_checked_at includes failed attempts. paid_messages.paused reflects local billing pauses on your project’s attachment only. It is not an authorization promise — balance, credentials, Meta restrictions and the partner send pipeline can still block sending, and a funded WABA can have paused messages. Treat reason as an extensible machine-readable string and message as display copy. operation is the latest funding run for this WABA in your project, or null when no run was ever started:
Run states are pending, running, succeeded, failed, cancelled and expired. A terminal run does not promise funding — read both the funding status and reason. error_kind is an extensible machine-readable string; provider messages and credentials are never exposed.

Ensure funding

After Embedded Signup completes, ensure funding for an external multi-partner solution account without waiting for the Meta association webhook:
Your project must have exactly one active external multi-partner solution. You cannot select a solution or project, set the WABA currency, or supply a token. When the membership is unknown, Kapso reads the WABA through that solution and verifies its owning portfolio — the only synchronous Meta call in these endpoints — before recording the association. Financial setup then runs in the background as a funding run. 202 means a run is pending or running; it is not confirmation that the account is funded. Poll GET /whatsapp/accounts/{waba_id}/funding until the run is terminal and the funding status is funded. 200 is returned when the account is already funded or no new run was started. There is no Idempotency-Key. Repeated calls reuse an in-progress run, and during a 30 second cooldown the previous terminal run is returned. After the cooldown a new run starts. Repeating the request never creates duplicate funding. The endpoint never resumes an explicitly disabled portfolio, a removed membership, or a revoked attachment — reconnecting stays an explicit workflow. Currency is not defaulted: discovery can succeed and the funding run still fail when the WABA has no currency. Errors: 400 invalid waba_id or business_portfolio_id, 401 invalid API key, 409 conflicting state (no single active external solution, funding disabled for the portfolio, the WABA owned by another portfolio, project or solution, unconfirmed Meta ownership, or a removed membership or attachment), 502 Meta could not verify access — no local records are created, and the body carries error_kind, meta_error_code and meta_trace_id — and 503 contention or queue unavailable, safe to retry.

Portfolio accounts

GET /whatsapp/portfolios/{portfolio_id}/accounts always uses cursor pagination, ordered by creation time descending. Use limit (default 20, max 100), after and before; pass paging.next back unchanged as after. Each item has the funding fields above, with operation always null — read the account endpoint for run state. A listed account is not necessarily funded or currently reachable in Meta — evidence is retained after disconnection.

Usage

Both usage endpoints require ISO 8601 start_time and end_time with an offset or Z, at most 31 days apart. The range is [start_time, end_time).
Amounts are integer micro-USD: 1000000 is USD 1. The window measures when charges were recorded, not when Meta delivered the messages. Signed corrections are included, so a correction-only window can return a negative total. Free messages, unposted observations and Meta charges paid outside Kapso are excluded. A zero total means zero recorded charges, not proof of zero spend. totals.customer_charge_micro_usd is the sum of every breakdown charge — what Kapso recorded, not Meta’s full invoice. New usage kinds can be added to breakdown, so handle unknown usage_kind values, don’t rely on array order, and read totals for the overall amount. Quantities belong to their kind: billable_messages is messaging-only, and calling reports aggregate fees rather than call counts, minutes or per-call charges.

Freshness

Each breakdown entry has its own sync, describing current observation health, not completeness of the requested range:
  • synced — every relevant account is fresh (messaging settled within 15 minutes, calling coverage under one hour old).
  • delayed — evidence exists but at least one account is older than that boundary.
  • unknown — at least one relevant account has no successful observation.
  • not_available — no coverage applies: a direct managed-billing account for messaging, or no active USD attachment for calling. Totals are still returned.
For messaging, last_synced_at is the oldest latest successful settlement and usage_through is the conservative common end of the processed query windows, capped at fetch completion. For calling, last_synced_at is always null — calling stores a reconciled coverage watermark rather than a settlement completion timestamp, and usage_through is the oldest such watermark across USD attachments. Neither guarantees Meta has reported everything for that period or will never revise it.

Calling coverage

Calling entries also carry coverage, based on the currency of your currently active attachments:
  • supported — every active attachment is a USD WABA.
  • partial — mixed USD and non-USD (reason: calling_requires_usd_waba). Fresh USD observations say nothing about the non-USD WABAs.
  • unsupported — no USD attachment (reason: calling_requires_usd_waba).
  • not_available — no active attachment (reason: no_active_attachment).
Coverage is not a promise of billing activation, working credentials or complete observations, and historical calling charges stay in the total even after support is lost. Poll these endpoints if you need spend visibility, but do not use delayed usage as a real-time hard credit limit. Portfolio totals include only your project’s charges.

Stop portfolio funding

No body is required. Use a stable unique Idempotency-Key (1–255 bytes) per logical request and reuse it after an HTTP or network failure — the original operation is returned, and an interrupted queue submission is recovered. Reusing a key for a different portfolio returns 409. 202 is acceptance, not confirmation that Meta funding stopped. Poll /whatsapp/portfolios/{portfolio_id}/funding/operations/{operation_id} until succeeded or failed. States are queued, running, succeeded, failed and superseded. A failed operation can be partially completed — inspect WABA funding and contact support before starting a new one. Operations are readable after the WABA moves or is disconnected. The control disables portfolio auto-funding and revokes each approved allocation in the validated scope, so every WABA using that allocation is affected, not just one number. Allocations Kapso did not create, or whose liability includes another portfolio or project, are rejected. Accounts that change between acceptance and execution make the operation fail safely. Revoking funding does not disconnect numbers, remove a partner, erase billing history, or forgive outstanding usage. Customers may need their own Meta payment method afterwards. Errors: 400 invalid input or key, 401 invalid API key, 404 unknown or invisible resource, 409 unsafe scope or conflicting key, 503 queue unavailable. Provider errors and secrets are never included in operation responses.