Miden Open API Docs
openapi: 3.0.3
info:
title: Miden Kenya – Crypto Payment Gateway API
version: 1.1.0
description: |
Accept crypto (USDT, USDC, BTC, ETH), auto-convert, and settle to Kenyan rails: M-Pesa, Airtel Money, T-Kash, and PesaLink.
Custody, MPC signing and hot/cold workflows are handled via Fireblocks. All local payouts are in KES.
Key improvements in v1.1.0:
- Token lifecycle clarified (expiry, rotation), optional scopes
- Idempotency header documented and enforced on POST creates
- On-chain confirmation policy per asset
- Rate limits + headers
- Detailed error catalog with machine codes
- Webhook signature (HMAC) + retry policy
- Sandbox test data and rail-specific examples
servers:
- url: https://api.midenkenya.com/v1
description: Production
- url: https://sandbox.api.midenkenya.com/v1
description: Sandbox
security:
- bearerAuth: []
- oauth2ClientCreds: []
externalDocs:
description: Developer portal
url: https://midenkenya.com/docs
x-idempotency:
header: Idempotency-Key
description: Unique per creating request to guarantee exactly-once semantics. Required on all POST create endpoints.
tags:
- name: Auth
- name: Payments – USDT
- name: Payments – USDC
- name: Payments – BTC
- name: Payments – ETH
- name: Settlements – M-Pesa
- name: Settlements – Airtel Money
- name: Settlements – T-Kash
- name: Settlements – PesaLink
- name: Refunds
- name: Directory
- name: Webhooks
paths:
/auth/token:
post:
tags: [Auth]
summary: Obtain OAuth2 access token (Client Credentials)
description: |
Exchange `client_id` and `client_secret` for a short-lived JWT. Default expiry is 3600 seconds.
Rotate client secrets at least quarterly. Optional scopes are reserved for future RBAC.
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TokenRequest' }
example:
client_id: your_client_id
client_secret: your_client_secret
grant_type: client_credentials
responses:
'200':
description: Access token
headers:
X-RateLimit-Limit: { $ref: '#/components/headers/X-RateLimit-Limit' }
X-RateLimit-Remaining: { $ref: '#/components/headers/X-RateLimit-Remaining' }
content:
application/json:
schema: { $ref: '#/components/schemas/TokenResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
############################
# PAYMENTS (per asset)
############################
/payments/usdt:
post:
tags: [Payments – USDT]
summary: Create USDT payment (quote + deposit address)
description: |
Supported networks: ETH (ERC-20), TRX (TRC-20). Quote expires at `quote.expires_at`.
On-chain confirmation policy: 12 blocks (ETH), 20 blocks (TRX) before status becomes CONFIRMED.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PaymentCreateUSDT' }
example:
network: ETH
amount_fiat: 1000
currency: KES
customer_reference: ORDER-123
callback_url: https://merchant.example/callback
responses:
'201':
description: Payment created
headers:
X-RateLimit-Limit: { $ref: '#/components/headers/X-RateLimit-Limit' }
X-RateLimit-Remaining: { $ref: '#/components/headers/X-RateLimit-Remaining' }
content:
application/json:
schema: { $ref: '#/components/schemas/Payment' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/payments/usdc:
post:
tags: [Payments – USDC]
summary: Create USDC payment (quote + deposit address)
description: |
Supported network: ETH (ERC-20). Confirmation policy: 12 blocks before CONFIRMED.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PaymentCreateUSDC' }
example:
network: ETH
amount_fiat: 32500
currency: KES
customer_reference: SO-98234
callback_url: https://merchant.example/callback
responses:
'201':
description: Payment created
headers:
X-RateLimit-Limit: { $ref: '#/components/headers/X-RateLimit-Limit' }
X-RateLimit-Remaining: { $ref: '#/components/headers/X-RateLimit-Remaining' }
content:
application/json:
schema: { $ref: '#/components/schemas/Payment' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/payments/btc:
post:
tags: [Payments – BTC]
summary: Create BTC payment (quote + deposit address)
description: |
Supported network: BTC (native). Confirmation policy: 1 block for low value, 3 blocks standard before CONFIRMED.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PaymentCreateBTC' }
example:
amount_fiat: 5000
currency: KES
customer_reference: INV-2025-045
callback_url: https://merchant.example/callback
responses:
'201':
description: Payment created
headers:
X-RateLimit-Limit: { $ref: '#/components/headers/X-RateLimit-Limit' }
X-RateLimit-Remaining: { $ref: '#/components/headers/X-RateLimit-Remaining' }
content:
application/json:
schema: { $ref: '#/components/schemas/Payment' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/payments/eth:
post:
tags: [Payments – ETH]
summary: Create ETH payment (quote + deposit address)
description: |
Supported network: ETH (native). Confirmation policy: 12 blocks before CONFIRMED.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PaymentCreateETH' }
example:
amount_fiat: 12000
currency: KES
customer_reference: ORD-8842
callback_url: https://merchant.example/callback
responses:
'201':
description: Payment created
headers:
X-RateLimit-Limit: { $ref: '#/components/headers/X-RateLimit-Limit' }
X-RateLimit-Remaining: { $ref: '#/components/headers/X-RateLimit-Remaining' }
content:
application/json:
schema: { $ref: '#/components/schemas/Payment' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/payments/{payment_id}:
get:
tags: [Payments – USDT, Payments – USDC, Payments – BTC, Payments – ETH]
summary: Retrieve a payment by ID
security: [{ bearerAuth: [] }]
parameters:
- name: payment_id
in: path
required: true
schema: { type: string }
responses:
'200':
description: Payment
content:
application/json:
schema: { $ref: '#/components/schemas/Payment' }
'404': { $ref: '#/components/responses/NotFound' }
############################
# SETTLEMENTS (per rail)
############################
/settlements/mpesa:
post:
tags: ['Settlements – M-Pesa']
summary: Create M-Pesa settlement
description: |
Payout to Safaricom M-Pesa wallet. Recipient MSISDN format: `2547XXXXXXXX`.
Provider: https://www.safaricom.co.ke/m-pesa
Limits vary by recipient tier; large payouts should be split automatically.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/MpesaSettlementRequest' }
example:
payment_id: pay_01J8E9W4C2XJ9
channel: MPESA
recipient_number: '254712345678'
amount: 1000
narration: 'Invoice #1234'
responses:
'201': { description: Settlement created, content: { application/json: { schema: { $ref: '#/components/schemas/MobileMoneySettlementResponse' } } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/settlements/airtel:
post:
tags: ['Settlements – Airtel Money']
summary: Create Airtel Money settlement
description: |
Payout to Airtel Money wallet. Recipient format: `2547XXXXXXXX`.
Provider: https://www.airtelmoney.ke/
Airtel may enforce tighter velocity limits; batch intelligently.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/AirtelSettlementRequest' }
example:
payment_id: pay_01J8E9W4C2XJ9
channel: AIRTEL
recipient_number: '254733000000'
amount: 1000
narration: 'Payout AUG-25'
responses:
'201': { description: Settlement created, content: { application/json: { schema: { $ref: '#/components/schemas/MobileMoneySettlementResponse' } } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/settlements/tkash:
post:
tags: ['Settlements – T-Kash']
summary: Create T-Kash settlement
description: |
Payout to Telkom T-Kash. Recipient format: `2547XXXXXXXX`.
Provider: https://telkom.co.ke/t-kash/
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TkashSettlementRequest' }
example:
payment_id: pay_01J8E9W4C2XJ9
channel: TKASH
recipient_number: '254770000000'
amount: 1500
responses:
'201': { description: Settlement created, content: { application/json: { schema: { $ref: '#/components/schemas/MobileMoneySettlementResponse' } } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/settlements/pesalink:
post:
tags: ['Settlements – PesaLink']
summary: Create PesaLink settlement (bank-to-bank)
description: |
Interbank settlement via IPSL through sponsor bank/aggregator.
Provider: https://www.pesalink.co.ke/
Always capture and persist `rrn` for reconciliation.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/PesalinkSettlementRequest' }
example:
payment_id: pay_01J8E9W4C2XJ9
channel: PESALINK
bank_code: KCBL
account_number: '1234567890'
account_name: 'ACME LTD'
amount: 100000
narration: 'Invoice 2025-0198'
reference: 'INV-2025-0198'
responses:
'201': { description: Settlement created, content: { application/json: { schema: { $ref: '#/components/schemas/PesalinkSettlementResponse' } } } }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/settlements/{settlement_id}:
get:
tags: ['Settlements – M-Pesa', 'Settlements – Airtel Money', 'Settlements – T-Kash', 'Settlements – PesaLink']
summary: Get settlement status
security: [{ bearerAuth: [] }]
parameters:
- name: settlement_id
in: path
required: true
schema: { type: string }
responses:
'200':
description: Settlement status
content:
application/json:
schema: { oneOf: [ { $ref: '#/components/schemas/MobileMoneySettlementStatus' }, { $ref: '#/components/schemas/PesalinkSettlementStatus' } ] }
'404': { $ref: '#/components/responses/NotFound' }
############################
# DIRECTORY & REFUNDS
############################
/directory/pesalink/banks:
get:
tags: [Directory]
summary: List PesaLink participant banks
security: [{ bearerAuth: [] }]
responses:
'200':
description: Bank directory
content:
application/json:
schema:
type: array
items: { $ref: '#/components/schemas/PesalinkBank' }
/refunds:
post:
tags: [Refunds]
summary: Create a refund
description: Refund on-chain or to a local rail.
security: [{ bearerAuth: [] }]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/RefundCreateRequest' }
examples:
mpesa:
value:
payment_id: pay_01J8E9W4C2XJ9
amount: 500
method: MPESA
destination: { recipient_number: '254712345678' }
reason: Customer cancellation
onchain:
value:
payment_id: pay_01J8E9W4C2XJ9
amount: 7.83
method: ONCHAIN
destination: { asset: USDT, network: ETH, address: '0xabc...' }
reason: Partial refund
responses:
'201':
description: Refund created
content:
application/json:
schema: { $ref: '#/components/schemas/Refund' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'409': { $ref: '#/components/responses/Conflict' }
/refunds/{refund_id}:
get:
tags: [Refunds]
summary: Retrieve a refund
security: [{ bearerAuth: [] }]
parameters:
- name: refund_id
in: path
required: true
schema: { type: string }
responses:
'200':
description: Refund
content:
application/json:
schema: { $ref: '#/components/schemas/Refund' }
'404': { $ref: '#/components/responses/NotFound' }
############################
# WEBHOOKS (outbound)
############################
/webhooks/test:
post:
tags: [Webhooks]
summary: Trigger a test webhook to your endpoint (sandbox only)
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url: { type: string, format: uri }
event: { type: string, enum: [payment.confirmed, settlement.success, settlement.failed, settlement.reversed] }
responses:
'202': { description: Test webhook scheduled }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
oauth2ClientCreds:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://api.midenkenya.com/v1/auth/token
scopes: {}
headers:
X-RateLimit-Limit:
description: Requests allowed in the current window
schema: { type: integer }
X-RateLimit-Remaining:
description: Requests remaining in the current window
schema: { type: integer }
Retry-After:
description: Seconds to wait before retrying (returned on 429)
schema: { type: integer }
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
description: Unique key to ensure exactly-once processing of create requests
schema: { type: string }
responses:
BadRequest:
description: Bad request
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Unauthorized:
description: Unauthorized or invalid token
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
NotFound:
description: Resource not found
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Conflict:
description: Duplicate or conflicting request
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
schemas:
############################
# AUTH
############################
TokenRequest:
type: object
required: [client_id, client_secret, grant_type]
properties:
client_id: { type: string }
client_secret: { type: string }
grant_type:
type: string
enum: [client_credentials]
TokenResponse:
type: object
properties:
access_token: { type: string }
token_type: { type: string, example: Bearer }
expires_in: { type: integer, example: 3600 }
############################
# PAYMENTS
############################
PaymentCreateUSDT:
type: object
required: [network, amount_fiat, currency]
properties:
network:
type: string
enum: [ETH, TRX]
amount_fiat: { type: number, format: double, minimum: 1 }
currency:
type: string
enum: [KES]
customer_reference: { type: string }
callback_url: { type: string, format: uri }
metadata:
type: object
additionalProperties: { type: string }
PaymentCreateUSDC:
type: object
required: [network, amount_fiat, currency]
properties:
network:
type: string
enum: [ETH]
amount_fiat: { type: number, format: double, minimum: 1 }
currency:
type: string
enum: [KES]
customer_reference: { type: string }
callback_url: { type: string, format: uri }
metadata:
type: object
additionalProperties: { type: string }
PaymentCreateBTC:
type: object
required: [amount_fiat, currency]
properties:
amount_fiat: { type: number, format: double, minimum: 1 }
currency:
type: string
enum: [KES]
customer_reference: { type: string }
callback_url: { type: string, format: uri }
metadata:
type: object
additionalProperties: { type: string }
PaymentCreateETH:
type: object
required: [amount_fiat, currency]
properties:
amount_fiat: { type: number, format: double, minimum: 1 }
currency:
type: string
enum: [KES]
customer_reference: { type: string }
callback_url: { type: string, format: uri }
metadata:
type: object
additionalProperties: { type: string }
Payment:
type: object
properties:
payment_id: { type: string }
asset: { type: string, enum: [USDT, USDC, BTC, ETH] }
network: { type: string, nullable: true }
status: { type: string, enum: [PENDING, CONFIRMED, EXPIRED, CANCELLED] }
quote:
type: object
properties:
amount_fiat: { type: number }
currency: { type: string, enum: [KES] }
expected_asset_amount: { type: string }
rate: { type: string, description: Fiat-to-asset rate used }
expires_at: { type: string, format: date-time }
deposit:
type: object
properties:
address: { type: string }
memo: { type: string, nullable: true }
qr: { type: string, description: Base64 PNG data URL }
amount_received: { type: string }
fiat_equivalent: { type: number }
customer_reference: { type: string, nullable: true }
created_at: { type: string, format: date-time }
confirmed_at: { type: string, format: date-time, nullable: true }
metadata:
type: object
additionalProperties: { type: string }
############################
# SETTLEMENTS
############################
MpesaSettlementRequest:
type: object
required: [payment_id, channel, recipient_number, amount]
properties:
payment_id: { type: string }
channel: { type: string, enum: [MPESA] }
recipient_number:
type: string
description: MSISDN in international format, e.g., 2547XXXXXXXX
pattern: '^2547\d{8}$'
amount: { type: number, format: double, minimum: 1 }
narration: { type: string, maxLength: 40 }
metadata:
type: object
additionalProperties: { type: string }
AirtelSettlementRequest:
type: object
required: [payment_id, channel, recipient_number, amount]
properties:
payment_id: { type: string }
channel: { type: string, enum: [AIRTEL] }
recipient_number:
type: string
description: MSISDN in international format, e.g., 2547XXXXXXXX
pattern: '^2547\d{8}$'
amount: { type: number, format: double, minimum: 1 }
narration: { type: string, maxLength: 40 }
metadata:
type: object
additionalProperties: { type: string }
TkashSettlementRequest:
type: object
required: [payment_id, channel, recipient_number, amount]
properties:
payment_id: { type: string }
channel: { type: string, enum: [TKASH] }
recipient_number:
type: string
description: MSISDN in international format
pattern: '^2547\d{8}$'
amount: { type: number, format: double, minimum: 1 }
narration: { type: string, maxLength: 40 }
metadata:
type: object
additionalProperties: { type: string }
PesalinkSettlementRequest:
type: object
required: [payment_id, channel, bank_code, account_number, account_name, amount]
properties:
payment_id: { type: string }
channel: { type: string, enum: [PESALINK] }
bank_code: { type: string, example: KCBL }
account_number: { type: string }
account_name: { type: string }
amount: { type: number, format: double, minimum: 1 }
narration: { type: string, maxLength: 40 }
reference: { type: string, description: Merchant reference for reconciliation }
proxy_type:
type: string
enum: [PHONE, ACCOUNT]
nullable: true
proxy_value: { type: string, nullable: true }
metadata:
type: object
additionalProperties: { type: string }
MobileMoneySettlementResponse:
type: object
properties:
settlement_id: { type: string }
channel: { type: string, enum: [MPESA, AIRTEL, TKASH] }
status: { type: string, enum: [PROCESSING, SUCCESS, FAILED, REVERSED] }
amount: { type: number }
currency: { type: string, enum: [KES] }
beneficiary:
type: object
properties:
recipient_number: { type: string }
provider_reference: { type: string, nullable: true }
created_at: { type: string, format: date-time }
completed_at: { type: string, format: date-time, nullable: true }
MobileMoneySettlementStatus:
type: object
properties:
settlement_id: { type: string }
status: { type: string, enum: [PROCESSING, SUCCESS, FAILED, REVERSED] }
provider_reference: { type: string, nullable: true }
failure_reason: { type: string, nullable: true }
completed_at: { type: string, format: date-time, nullable: true }
PesalinkSettlementResponse:
type: object
properties:
settlement_id: { type: string }
channel: { type: string, enum: [PESALINK] }
status: { type: string, enum: [PROCESSING, SUCCESS, FAILED, REVERSED] }
amount: { type: number }
currency: { type: string, enum: [KES] }
beneficiary:
type: object
properties:
bank_code: { type: string }
account_number: { type: string }
account_name: { type: string }
rrn: { type: string, description: IPSL Retrieval Reference Number }
reference: { type: string, nullable: true }
created_at: { type: string, format: date-time }
completed_at: { type: string, format: date-time, nullable: true }
PesalinkSettlementStatus:
type: object
properties:
settlement_id: { type: string }
status: { type: string, enum: [PROCESSING, SUCCESS, FAILED, REVERSED] }
rrn: { type: string, nullable: true }
bank_response_code: { type: string, nullable: true }
failure_reason: { type: string, nullable: true }
completed_at: { type: string, format: date-time, nullable: true }
PesalinkBank:
type: object
properties:
bank_code: { type: string }
bank_name: { type: string }
############################
# REFUNDS & ERROR
############################
RefundCreateRequest:
type: object
required: [payment_id, amount, method]
properties:
payment_id: { type: string }
amount: { type: number, format: double, minimum: 1 }
method:
type: string
enum: [ONCHAIN, MPESA, AIRTEL, TKASH, PESALINK]
destination:
type: object
description: Destination details required for local-rail refunds
additionalProperties: true
reason: { type: string }
Refund:
type: object
properties:
refund_id: { type: string }
payment_id: { type: string }
amount: { type: number }
method: { type: string }
status: { type: string, enum: [PENDING, PROCESSING, SUCCESS, FAILED] }
created_at: { type: string, format: date-time }
completed_at: { type: string, format: date-time, nullable: true }
Error:
type: object
properties:
code:
type: string
enum:
- INVALID_REQUEST
- UNAUTHORIZED
- NOT_FOUND
- CONFLICT
- RATE_LIMITED
- PROVIDER_DOWN
- INVALID_MSISDN
- LIMIT_EXCEEDED
- NAME_MISMATCH
- INSUFFICIENT_LIQUIDITY
- RISK_BLOCKED
- INTERNAL_ERROR
message: { type: string }
trace_id: { type: string }
details:
type: object
additionalProperties: true
x-webhooks:
payment.confirmed:
post:
tags: [Webhooks]
summary: Payment confirmed on-chain
description: |
Sent when crypto funds meet the confirmation policy and are locked for settlement.
Verify signatures using HMAC SHA-256 over raw body with your webhook secret provided in the dashboard.
Header: `X-Miden-Signature: t=timestamp,v1=hexdigest`.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
event: { type: string, example: payment.confirmed }
data:
type: object
properties:
payment_id: { type: string }
asset: { type: string, enum: [USDT, USDC, BTC, ETH] }
network: { type: string }
amount_received: { type: string }
fiat_equivalent: { type: number }
confirmed_at: { type: string, format: date-time }
responses:
'200': { description: Acknowledge }
settlement.success:
post:
tags: [Webhooks]
summary: Settlement succeeded
description: Retries with exponential backoff up to 24 hours if your endpoint returns non-2xx.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
event: { type: string, example: settlement.success }
data:
type: object
properties:
settlement_id: { type: string }
channel: { type: string, enum: [MPESA, AIRTEL, TKASH, PESALINK] }
amount: { type: number }
currency: { type: string, enum: [KES] }
provider_reference: { type: string, nullable: true }
rrn: { type: string, nullable: true }
timestamp: { type: string, format: date-time }
responses:
'200': { description: Acknowledge }
settlement.failed:
post:
tags: [Webhooks]
summary: Settlement failed
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
event: { type: string, example: settlement.failed }
data:
type: object
properties:
settlement_id: { type: string }
channel: { type: string }
amount: { type: number }
failure_reason: { type: string }
timestamp: { type: string, format: date-time }
responses:
'200': { description: Acknowledge }
settlement.reversed:
post:
tags: [Webhooks]
summary: Settlement reversed
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
event: { type: string, example: settlement.reversed }
data:
type: object
properties:
settlement_id: { type: string }
channel: { type: string }
amount: { type: number }
reason: { type: string }
timestamp: { type: string, format: date-time }
responses:
'200': { description: Acknowledge }
x-sandbox:
mpesa:
test_msisdn: '254700000000'
airtel:
test_msisdn: '254733000000'
tkash:
test_msisdn: '254770000000'
pesalink:
demo_bank_code: 'DEMO'
down_bank_code: 'DOWN'
name_mismatch_amount_trigger: 1234