Offline Payments
Load a device online, pay offline, settle in batches when it reconnects, with replay protection. About offline payments Live
- POST
/offline/depositDeposit into the caller's device wallet from their own main account - POST
/offline/identityIssue a signed offline identity assertion for one of the caller's linked devices - POST
/offline/settlementReconcile a batch of offline peer-to-peer taps into the real ledger
POST Deposit into the caller's device wallet from their own main account
POST /offline/deposit
Requires a validated transaction PIN and device (x-secret-value/x-device-id headers on this request) - both must have been validated, and the body's deviceId must be the specific device currently linked to the caller's device wallet. An optional Idempotency-Key header makes a retried call with the same key return the original result instead of moving funds again.
Headers
| Name | Notes |
|---|---|
Authorization | Bearer token |
X-Tenant | Your tenant |
X-Environment | test or live |
X-Idempotency-Key | Reuse the same value on every retry of this request |
Content-Type | application/json |
Example
Request body: TopupRequest · Response: TopupResponse
curl -X POST "https://api.bridgemoni.com/offline/deposit" \
-H "Authorization: Bearer $BRIDGEMONI_TOKEN" \
-H "X-Tenant: $BRIDGEMONI_TENANT" \
-H "X-Environment: $BRIDGEMONI_ENV" \
-H "X-Idempotency-Key: a-unique-key-per-intent" \
-H "Content-Type: application/json" \
-d '{
"amount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"narration": "March payroll",
"deviceId": "a7f3-k2m9-4c1d-8e5b"
}' {
"amount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"narration": "March payroll",
"deviceId": "a7f3-k2m9-4c1d-8e5b"
} {
"data": {
"topupReference": "b3f1c2d4-5e6a-4b7c-8d9e-0f1a2b3c4d5e",
"sourceAccountNumber": "0123456789",
"destinationAccountNumber": "0123456789",
"amount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"netAmount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"status": "PENDING",
"accountsTransactionReference": "financial transaction reference",
"approvalReference": "b3f1c2d4-5e6a-4b7c-8d9e-0f1a2b3c4d5e",
"timestamp": "2027-03-14T14:30:01"
},
"description": "Deposit into the caller's device wallet from their own main account"
} Responses
| Status | When |
|---|---|
200 | Deposit processed successfully |
POST Issue a signed offline identity assertion for one of the caller's linked devices
POST /offline/identity
Two phones settling a payment with no network cannot look each other up, so each carries a statement signed by us saying which user a device public key belongs to. The receiving phone verifies that signature with no connectivity at all. Safe and cheap to call repeatedly - a device renews after linking, after a deposit, after a settlement that leaves a balance, and whenever the app opens online without a valid assertion. Nothing is issued for a key that is not a device currently linked to the caller, or for a blocked or closed account.
Headers
| Name | Notes |
|---|---|
Authorization | Bearer token |
X-Tenant | Your tenant |
X-Environment | test or live |
Content-Type | application/json |
Example
Request body: OfflineIdentityRequest · Response: GenericResponseOfflineIdentityResponse
curl -X POST "https://api.bridgemoni.com/offline/identity" \
-H "Authorization: Bearer $BRIDGEMONI_TOKEN" \
-H "X-Tenant: $BRIDGEMONI_TENANT" \
-H "X-Environment: $BRIDGEMONI_ENV" \
-H "Content-Type: application/json" \
-d '{
"identityPublicKey": "string"
}' {
"identityPublicKey": "string"
} {
"data": {
"identityAssertion": "string",
"identityAssertionSignature": "string",
"assertionPublicKey": "string"
},
"description": "Offline identity assertion issued"
} Responses
| Status | When |
|---|---|
200 | Offline identity assertion issued |
POST Reconcile a batch of offline peer-to-peer taps into the real ledger
POST /offline/settlement
Requires a validated transaction PIN and device (x-secret-value/x-device-id headers on this request) for the caller's own side of each transaction. Each item already carries both parties' signatures over its canonical payload - whichever side calls first performs the real, one-time movement from the sender's device account to the receiver's main account; the other side's later call for the same sender/receiver transaction reference pair is a no-op returning the already-COMPLETED result. A failed item is reported with FAILED status in its own result entry rather than aborting the rest of the batch.
Headers
| Name | Notes |
|---|---|
Authorization | Bearer token |
X-Tenant | Your tenant |
X-Environment | test or live |
Content-Type | application/json |
Example
Request body: OfflineSettlementRequest · Response: OfflineSettlementResponse
curl -X POST "https://api.bridgemoni.com/offline/settlement" \
-H "Authorization: Bearer $BRIDGEMONI_TOKEN" \
-H "X-Tenant: $BRIDGEMONI_TENANT" \
-H "X-Environment: $BRIDGEMONI_ENV" \
-H "Content-Type: application/json" \
-d '{
"transactions": [
{
"amount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"narration": "March payroll",
"senderTransactionReference": "financial transaction reference",
"receiverTransactionReference": "financial transaction reference",
"senderMsisdn": "+2348012345678",
"receiverMsisdn": "+2348012345678",
"role": "SENDER",
"senderSignature": "signature data",
"receiverSignature": "signature data",
"callerDeviceId": "a7f3-k2m9-4c1d-8e5b"
}
]
}' {
"transactions": [
{
"amount": {
"amount": "250000.00",
"currencyCode": "NGN"
},
"narration": "March payroll",
"senderTransactionReference": "financial transaction reference",
"receiverTransactionReference": "financial transaction reference",
"senderMsisdn": "+2348012345678",
"receiverMsisdn": "+2348012345678",
"role": "SENDER",
"senderSignature": "signature data",
"receiverSignature": "signature data",
"callerDeviceId": "a7f3-k2m9-4c1d-8e5b"
}
]
} {
"data": {
"settlements": [
{
"settlementReference": "b3f1c2d4-5e6a-4b7c-8d9e-0f1a2b3c4d5e",
"status": "PENDING"
}
]
},
"description": "Reconcile a batch of offline peer-to-peer taps into the real ledger"
} Responses
| Status | When |
|---|---|
200 | Settlement batch processed |
Generated from the OpenAPI document. Branch on the HTTP status: there is no machine-readable error code on the wire. Errors