Partner integration
The architecture separates three independent choices: entry channel, authorization mode and blockchain execution model. Choosing WhatsApp leaves the question of who signs and who broadcasts open; choosing external broadcast leaves the user's experience as it is.
Partner-app-first
sequenceDiagram
autonumber
participant U as User
participant APP as Partner app
participant PB as Partner backend
participant SDK as B2B SDK
participant API as B2B API
participant OP as Operation
participant SG as Partner signer
participant CH as Blockchain
participant R as Reconciler
participant WH as Webhook
U->>APP: Recipient, asset, amount
APP->>PB: Request quote
PB->>SDK: createQuote
SDK->>API: POST /v1/quotes
API-->>PB: Quote + fees + expiry
PB-->>APP: Show summary
U->>APP: Confirm
APP->>PB: Authenticated confirmation
PB->>SDK: createTransfer + idempotency key
SDK->>API: POST /v1/transfers
API-->>PB: operation_id
API->>OP: Process
OP->>SG: Request signature
SG-->>OP: Signature
OP->>CH: Broadcast
R->>CH: Receipt / finality
R->>OP: Reconcile
OP->>WH: Event
WH-->>PB: Signed webhook
PB-->>APP: Update statusWhat each step does
- User → Partner app. The person picks recipient, asset and amount in the Partner's own interface. The Partner owns the experience and the session.
- App → Partner backend. The app asks its own backend for the quote, which keeps the API credential off the device.
- Backend → SDK:
createQuote. The SDK is a typed client of the B2B API, and the caller works with the types of the contract. - SDK → API:
POST /v1/quotes. The tenant is derived from the authenticated credential. - API → backend: quote, fees and expiry. The quote carries the fee breakdown — network fee, provider fee, service fee, total — the policy version it was priced under, and the moment it expires. Amounts travel in integer minimum units.
- Backend → app: show the summary. The person sees the total they are about to authorize before deciding.
- User → app: confirmation. The confirmation is given against that summary, which is what binds it to the quote that was shown.
- App → backend: authenticated confirmation. The Partner applies its own authentication, KYC and risk rules here, where its user session lives.
- Backend → SDK:
createTransferwith an idempotency key. The key is what makes a retry safe: the same key returns the same operation instead of sending twice. - SDK → API:
POST /v1/transfers. - API → backend:
operation_id. The answer confirms acceptance, so the backend holds no open connection waiting for finality. - API → Operation: process. The
Operationis persisted with its reserve and its event, and from here the flow survives a restart. - Operation → Partner signer: request the signature. A
keyReferenceand a digest travel under the tenant's policy. - Signer → Operation: signature. It returns with an audit reference and a key version, and the API verifies it against the digest and the expected address.
- Operation → blockchain: broadcast. The adapter of the enabled network builds and submits the transaction.
- Reconciler → chain: receipt and finality. The observer waits for the depth agreed for this operation.
- Reconciler → Operation: reconcile. The amounts settled and the fees paid are contrasted against what was recorded.
- Operation → webhook dispatcher: event. The event is written in the same transaction as the change that caused it, so every state change has its event.
- Dispatcher → backend: signed webhook. Delivery is at-least-once, so the backend deduplicates by event identifier.
- Backend → app: update the status. The Partner rebuilds its own projection, and
GET Operationand the event cursor cover a delayed delivery.
Advantages: it integrates with the authentication, KYC, risk and UX already in place; the Partner controls the whole experience; webhooks feed the detail view.
Trade-offs: the Partner maintains a backend and a state projection; starting operations depends on the availability of its app and backend.
WhatsApp-first
sequenceDiagram
autonumber
participant U as User
participant WA as Partner WhatsApp
participant BOT as Partner conversational instance
participant API as B2B API
participant RR as Recipient Resolver
participant OP as Operation
participant SG as Partner signer
participant CH as Blockchain
participant PB as Partner backend
U->>WA: Send asset/amount to a contact
WA->>BOT: Inbound message
BOT->>API: Resolve + quote
API->>RR: Alias to ChainAccount
RR-->>API: Destination + state
API-->>BOT: Quote + fees
BOT-->>U: Summary and confirmation
U->>BOT: Confirm
BOT->>API: Create idempotent operation
API->>OP: Policy + limits + signature
OP->>SG: Request signature
SG-->>OP: Signature
OP->>CH: Broadcast
OP-->>BOT: State
OP-->>PB: Signed webhook
BOT-->>U: ResultWhat each step does
- User → WhatsApp. The person says what they want in plain words, on the Partner's own number.
- WhatsApp → conversational instance. The inbound message reaches the instance, which reads the intent and collects whatever is missing.
- Instance → API: resolve and quote. One request covers who the recipient is and what the transfer costs.
- API → Recipient Resolver: alias to ChainAccount. The alias is normalized and resolved inside the tenant.
- Resolver → API: destination and state. The answer carries the address and whether that account is already active on the network.
- API → instance: quote and fees. The same fee breakdown and expiry as any other channel.
- Instance → user: summary and confirmation. The person sees amount, recipient, fees and total before deciding.
- User → instance: confirmation. The explicit confirmation is what authorizes the operation in this channel. The phone number acts as an alias, and the authority to spend comes from the link between that alias and an enabled
TenantUser. - Instance → API: create the idempotent operation. The request carries the idempotency key and the evidence of the channel.
- API → Operation: policy, limits and signing policy. The API checks that the sender is linked and enabled, and applies the tenant's limits before anything is signed.
- Operation → Partner signer: request the signature.
- Signer → Operation: signature.
- Operation → blockchain: broadcast.
- Operation → instance: state. The conversation receives the state of the operation, and the person is told without having to ask again.
- Operation → Partner backend: signed webhook. The Partner's backend receives the same durable event, so its projection matches what happened in the conversation.
- Instance → user: result.
WhatsApp-first is still B2B when the user, tenant, WABA, policies, signer and financial relationship belong to the Partner. The phone number serves as a channel alias and as a way to resolve recipients, and the authority to move funds comes from the link to an enabled TenantUser.
Authorization modes from WhatsApp
| Mode | How it works | Advantage | Cost / limitation |
|---|---|---|---|
| Direct confirmation in WhatsApp | A linked user confirms the quote; B2B applies limits and signer policy | Least friction and least synchronous dependency | Requires strong linking, limits and risk controls |
| Partner callback | B2B asks the Partner backend for every operation | The Partner decides in real time | Adds latency and a dependency on that backend |
| Signed grant/assertion | The Partner issues an authorization scoped by scope, amount, nonce and expiry | Avoids a callback per operation | Requires issuance, revocation and replay protection |
| Step-up in the Partner app | WhatsApp starts it; the Partner app confirms the sensitive operation | Stronger security for higher risk | Changes channel and adds friction |
Initial baseline Direct confirmation in WhatsApp for previously linked users, under the tenant's limits and policy. The other modes can be enabled by risk or capability.
Partner callback
sequenceDiagram
autonumber
participant U as User
participant BOT as WhatsApp channel
participant API as B2B API
participant PB as Partner backend
participant OP as Operation
U->>BOT: Confirms the quote
BOT->>API: Confirmation + channel evidence
API->>PB: Request a decision
PB-->>API: approved / denied / step-up
API->>OP: Create only when authorized
API-->>BOT: Authorization outcomeThe Partner can run its own rules in real time. The contract defines the timeout, the idempotency and what happens while that backend is unavailable: a missing answer counts as a denial.
Signed grant
sequenceDiagram
autonumber
participant PB as Partner backend
participant BOT as WhatsApp channel
participant API as B2B API
participant OP as Operation
PB-->>BOT: Scoped grant
BOT->>API: Confirmed quote + grant
API->>API: Verify issuer/user/scope/limits/nonce/expiry
API->>OP: Create when the grant is valid
API-->>BOT: operation_id / rejectionThe grant reduces the synchronous dependency, and it needs expiry, revocation and replay protection. Its authority reaches as far as its scope, amount, nonce and expiry state.
Step-up in the Partner app
sequenceDiagram
autonumber
participant U as User
participant BOT as WhatsApp channel
participant API as B2B API
participant APP as Partner app
participant PB as Partner backend
participant OP as Operation
U->>BOT: Requests a sensitive operation
BOT->>API: Draft + quote
API-->>BOT: step-up required + challenge
BOT-->>U: Open the app / deep link
U->>APP: Confirms the challenge
APP->>PB: Authenticated confirmation
PB->>API: Resolve the challenge
API->>OP: Continue the operation
API-->>BOT: operation_idThe challenge is bound to the original draft and quote, so a reinforced confirmation applies to that operation alone.
Blockchain execution models
B2B coordinates the execution
Initial recommended model
The channel delivers an authorized intent. ChatterPay creates the Operation, builds the payload, asks the Partner-controlled signer for a signature, broadcasts, observes and reconciles.
sequenceDiagram
autonumber
participant P as Partner / channel
participant API as B2B API
participant SG as Partner signer
participant CH as Blockchain
participant R as Reconciler
P->>API: Authorized intent
API->>SG: Digest + keyReference
SG-->>API: Signature
API->>CH: Broadcast
R->>CH: Evidence
R-->>P: Webhook / stateThe Partner executes on-chain itself
ChatterPay can resolve the recipient and later import a reference to the external transaction. Keeping reconciliation equivalent requires linking that external operation deterministically to an Operation.
sequenceDiagram
autonumber
participant PB as Partner backend
participant API as B2B API
participant CH as Blockchain
PB->>API: Resolve the destination
API-->>PB: Address
PB->>CH: Build + sign + broadcast
CH-->>PB: tx_hash
PB->>API: Import tx_hash + intent reference
API->>CH: Observe / reconcile
API-->>PB: State / webhookChatterPay builds and the Partner broadcasts
ChatterPay validates the intent and returns a payload and digest. The Partner signs and broadcasts, and then returns the on-chain reference. This model requires an expiry, a policy binding and explicit treatment of an ambiguous broadcast.
sequenceDiagram
autonumber
participant PB as Partner backend
participant API as B2B API
participant SG as Partner signer
participant CH as Blockchain
participant R as Reconciler
PB->>API: Create Operation
API-->>PB: Payload/digest + expiry + policy binding
PB->>SG: Sign
SG-->>PB: Signature
PB->>CH: Broadcast
CH-->>PB: tx_hash / ambiguous result
PB->>API: Import the broadcast result
API->>R: Observe and reconcile
R-->>PB: Webhook / stateThe imported reference has to match the authorized payload exactly. Closing an Operation as successful requires a transaction hash that agrees with the intent, the chain and the expiry.
Comparison
| Responsibility | B2B coordinates | Partner executes | B2B builds / Partner broadcasts |
|---|---|---|---|
| User authentication | Partner/channel | Partner | Partner |
| Payload construction | ChatterPay | Partner | ChatterPay |
| Key control | Partner signer | Partner | Partner |
| Broadcast | ChatterPay worker | Partner | Partner |
| Durable Operation | Native | Requires import/link | Native + result callback |
| Ledger and reconciliation | Complete | Complete once evidence is imported | Complete after importing the broadcast |
| Integration complexity | Low/medium | High | High |
Reference combinations
| Channel | User authorization | Execution | Reference use |
|---|---|---|---|
| Partner app | Authenticated confirmation in the app | B2B coordinates | Main baseline |
| Direct confirmation by a linked user | B2B coordinates | Conversational baseline | |
| Step-up in the app | B2B coordinates | Higher risk or amount | |
| Partner callback | B2B coordinates | The Partner's own synchronous rule | |
| Partner app | Confirmation in the app | The Partner executes | Interoperability |
| Partner app | Confirmation in the app | B2B builds / the Partner broadcasts | Advanced interoperability |
How fast you may call
Authentication says who is calling; it says nothing about how often. Every authenticated route of this API is bounded, and three bounds are charged at once: per client, per tenant and for the deployment as a whole. The tenant bound is above one client's, so a Partner running a backend, a bot and a dashboard has room for all three — and cannot buy a fourth budget by registering a fourth client.
A request over a bound is answered 429 with Retry-After, before the work it asked for is
started: it costs the deployment nothing, and it consumes none of the bounds it did not exceed.
The problem document carries code: "RATE_LIMIT_EXCEEDED" and details.scope — client, tenant
or deployment — and never another caller's identifier.
What a bound is depends on what a route costs, not on how it is spelled: reads are the loosest,
writes are in between, and the routes that move money or spend the deployment's funds are the
tightest. /health is never bounded, because a throttled health check reports a deployment as down
for the reason that it is busy.
Retry-After is an instruction, not a hint. The official SDK waits it out rather than applying
a backoff of its own, and gives up instead of sleeping past your request timeout. A client that
retries sooner is refused again, for the same reason and at the same cost.
App and dashboards
The Partner app can be the only end-user UI. The recommended pattern is webhook for updates plus GET Operation and events for recovery. The SDK is a typed client of the B2B API: it holds credentials for that API and calls its endpoints, and signing stays with the Partner Signer Gateway.
To project the detail of an operation, the Partner can keep at least operation_id, state, type, network, asset, requested and received amounts, fee breakdown, on-chain references, timestamps, and error or review codes where they apply. The API and the events are the authoritative source when a webhook delivery is delayed.
Optional surfaces, separated by audience:
- a white-label portal for the Partner's users;
- a Chatizalo operations dashboard for conversations and channel;
- a B2B console for administration and control plane: networks, fees, limits and configuration.
Each surface keeps its own privileges and reaches its data through the API.
A possible evolution is a Partner Operations Console that brings the Chatizalo operation modules and the B2B configuration into one visual surface, while APIs, persistence, RBAC and audit stay separate.
| Audience | Typical surface | Scope |
|---|---|---|
partner_user | Partner app / white-label portal | Their own wallets, balances and operations |
partner_support | Operations dashboard | Conversations and operational reading |
partner_admin | B2B console | Allowed configuration, limits, webhooks and capabilities |
chatterpay_support | Cross-component support | Scoped and audited diagnosis |
chatterpay_admin | Technical administration | Privileged and audited operation |
Capabilities in this area
This area covers the capabilities below. The Roadmap states the current availability of each one.
B2B API and asynchronous operations — The Partner sends an operation and immediately receives an identifier and a state. Settlement takes as long as the network takes, so the final state arrives through events or by querying the operation.
Official SDK — A typed client that handles authentication, idempotency keys, retries and the operation model. The Partner calls a method and receives the typed answer.
Portal and Sandbox backed by the SDK — The Sandbox on this site executes with the published SDK against a running B2B API. The requests it makes are the same ones a Partner's code makes.
Reference Partner and webhook receiver — An example application that authenticates against the API, sends operations and receives webhooks. It verifies the signature of every delivery and rejects the ones that do not verify.
OpenAPI, API and SDK fully synchronized — The OpenAPI specification, the implementation and the SDK are generated and checked from the same source. A field that is documented but not implemented, or the other way round, stops the build.
Bounds on how fast a credential may call — Every authenticated route is bounded per client, per tenant and for the deployment as a whole, and a caller over one of them is answered 429 with Retry-After before the work starts. Authentication says who is calling; it says nothing about how often.
Secure MCP API surface — Exposing the operations of the API as Model Context Protocol tools, with the same authentication, the same limits and the same human confirmation required from any other caller.