Moja SwitchDocs Sandbox live

Guide

Collections

Collect CAD from a payer by Interac request, then reconcile the payout to you. Sandbox only.

Sandbox only. Collections are available to sandbox API keys on the sandbox, after Moja Switch activates the collection product for your tenant. In production they are refused with 403 product_not_available; production collections and payouts are not offered yet.

A collection asks a payer in Canada to pay you in CAD by Interac request. Moja Switch collects the funds, then pays them out to you, net of fees, in a tenant payout. It uses the same endpoint as a transfer: POST /payments, with "kind": "collection".

The flow

sequenceDiagram
    autonumber
    participant You
    participant API as Moja Switch API
    participant Payer
    You->>API: POST /payments (kind: collection, Idempotency-Key)
    API-->>You: 201 Payment (id, status, funding_instructions)
    API->>Payer: Interac request for send_amount (CAD)
    Payer-->>API: Pays
    API-->>You: webhook payment.collected
    API-->>You: webhook payout.created, then payout.sent, payout.paid
    You->>API: GET /payouts/{payout_id} (reconcile by reference)

Create a collection

bash
curl -sS -X POST "$MOJA_BASE/payments" \
  -H "Authorization: Bearer $MOJA_KEY" \
  -H "Idempotency-Key: $(uuidgen | tr '[:upper:]' '[:lower:]')" \
  -H 'Content-Type: application/json' \
  -d '{
    "kind": "collection",
    "reference": "inv-2026-000123",
    "send_amount": { "value": "250.00", "currency": "CAD" },
    "funding_method": "INTERAC_REQUEST",
    "sender": { "email": "payer@example.com", "name": "Jordan Payer" },
    "payer_id": "payer-42",
    "destination_country": "TZ",
    "purpose": "FAMILY_SUPPORT",
    "sender_kyc": {
      "attested": true,
      "attestation_id": "kyc_ref_abc123",
      "attested_at": "2026-11-09T10:00:00Z"
    },
    "sandbox": { "collection_outcome": "paid" }
  }'
Field Rule
kind collection. Omit it, or send transfer, for a transfer.
reference Your unique reference. It reappears on the payout member, so make it the key you reconcile on.
send_amount CAD. Interac requests are limited to CAD 1.00 to 25,000.00 (422 amount_out_of_range).
funding_method Required: INTERAC_REQUEST.
sender The payer the Interac request is sent to: email and name only.
payer_id Your own stable identifier for the payer. It is the subject of your KYC attestation.
destination_country ISO 3166-1 alpha-2 country you will send the funds on to, outside Moja Switch.
purpose, sender_kyc Required. A missing or invalid attestation fails the collection at compliance.
quote_id, metadata Optional.
sandbox.collection_outcome Sandbox only: the simulated outcome. See below.

A collection must not carry corridor, payout, recipient_id, end_user_id or fx. Each violation is 422 validation_error with details[] naming the field. Without product activation you get 403 tenant_not_activated and nothing is created.

Statuses you will see

A collection moves through CREATED, VALIDATING, COMPLIANCE_CHECK and COLLECTING while the Interac request is out. If the payer does not pay, it ends FAILED with failure.code: collection_not_completed.

Known gap. The contract publishes the collection statuses COLLECTED, PAYOUT_SCHEDULED, PAID_OUT, REVERSED and CANCEL_REQUESTED, but GET /payments/{payment_id} does not emit them yet: once the payer has paid, a collection reads PROCESSING, and it stays there. The payment.collected webhook does carry status: COLLECTED. On a collection, funds_taken is not reliable yet, and corridor and payout carry placeholder values; ignore them. Accept all of the published statuses now, so that the fix is not a release for you.

Until then, treat the tenant payout as the source of truth for collected money.

Reconcile the payout

Collected funds are batched into a tenant payout (tpo_…) in CAD.

bash
curl -sS "$MOJA_BASE/payouts" -H "Authorization: Bearer $MOJA_KEY"
curl -sS "$MOJA_BASE/payouts/tpo_…" -H "Authorization: Bearer $MOJA_KEY"

Each payout has a status (CREATED, SENT, PAID, FAILED, RETURNED), a net_amount_minor and members[]. Each member carries your collection reference with gross_amount_minor, fee_amount_minor and net_amount_minor. Amounts on payouts are integer minor units (CAD cents).

Webhooks: payout.created, payout.sent, payout.paid, payout.failed and payout.returned. See Webhooks.

Test every outcome

Set sandbox.collection_outcome on create, and the next payout's outcome with PUT /sandbox/payout-outcome. See Sandbox testing.