{"info":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","description":"<html><head></head><body><p>Appia Pay Merchant Collection API — enables merchants to accept bank transfer payments via Providus dynamic accounts.</p>\n<h2 id=\"authentication\">Authentication</h2>\n<p>All requests require an API key in the <code>Authorization</code> header:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>Authorization: Bearer sk_live_&lt;your_api_key&gt;\n</code></pre><p>API keys are 72 characters long: <code>sk_live_</code> prefix + 64 hex characters.</p>\n<h2 id=\"rate-limiting\">Rate Limiting</h2>\n<ul>\n<li><strong>100 requests</strong> per 60-second window per merchant</li>\n<li>Response headers: <code>X-RateLimit-Limit</code>, <code>X-RateLimit-Remaining</code>, <code>X-RateLimit-Reset</code></li>\n<li>Exceeding the limit returns HTTP 429 with a <code>Retry-After</code> header</li>\n</ul>\n<h2 id=\"base-url\">Base URL</h2>\n<p>Set the <code>base_url</code> environment variable to your target environment.</p>\n<h2 id=\"errors\">Errors</h2>\n<p>All error responses follow this format:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n  \"success\": false,\n  \"message\": \"Description of the error\"\n}\n</code></pre>\n<p>Common HTTP status codes:</p>\n<ul>\n<li><code>400</code> — Validation error (missing/invalid fields)</li>\n<li><code>401</code> — Invalid or missing API key</li>\n<li><code>403</code> — Merchant account is pending or suspended</li>\n<li><code>404</code> — Resource not found</li>\n<li><code>429</code> — Rate limit exceeded</li>\n<li><code>500</code> — Internal server error</li>\n<li><code>502</code> — Payment gateway error (Providus)</li>\n<li><code>503</code> — Feature temporarily disabled</li>\n</ul>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"9242448","collectionId":"d4b44c70-0e5b-4048-bc2d-038b73404b37","publishedId":"2sBXcHjf56","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"732cdA"},"publishDate":"2026-03-02T15:19:36.000Z"},"item":[{"name":"Getting Started","item":[{"name":"API Overview","id":"1685e95a-21fe-476a-aa9c-c96977b3c3c2","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"<h2 id=\"appia-merchant-collection-api\">Appia Merchant Collection API</h2>\n<p>This API allows merchants to accept bank transfer payments in Nigeria via Providus Bank dynamic accounts.</p>\n<h3 id=\"how-it-works\">How It Works</h3>\n<ol>\n<li><strong>Initialize</strong> — Call <code>POST /merchant/initialize</code> with the payment amount and your unique reference. You receive a Providus bank account number.</li>\n<li><strong>Customer Pays</strong> — Share the account details with your customer. They make a bank transfer to the provided account.</li>\n<li><strong>Webhook</strong> — When payment is received, Appia sends a webhook to your configured URL with the <code>collection.successful</code> event.</li>\n<li><strong>Verify</strong> — Optionally call <code>GET /merchant/transaction/:ref</code> to confirm the payment status.</li>\n</ol>\n<h3 id=\"authentication\">Authentication</h3>\n<p>All API requests require a Bearer token:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>Authorization: Bearer sk_live_&lt;your_64_hex_char_key&gt;\n</code></pre><p>Your API key is provided during merchant onboarding. Keep it secret — treat it like a password.</p>\n<h3 id=\"rate-limits\">Rate Limits</h3>\n<ul>\n<li>100 requests per 60-second window</li>\n<li>Rate limit headers are included in every response</li>\n<li>HTTP 429 returned when limit is exceeded</li>\n</ul>\n<h3 id=\"setup\">Setup</h3>\n<ol>\n<li>Import the environment file and set your <code>merchant_api_key</code></li>\n<li>Set <code>base_url</code> to <code>https://api.appiawave.com</code> (or your staging URL)</li>\n<li>Set <code>webhook_receiver_url</code> to your webhook endpoint (for testing webhook payloads)</li>\n</ol>\n<hr />\n<p><em>Use this request to quickly verify your API key is working. A successful response means you are authenticated.</em></p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","balance"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"a1b402a9-d8a7-40b3-a0cf-ed6dae61d00b","name":"Success — Authenticated","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"## Appia Merchant Collection API\n\nThis API allows merchants to accept bank transfer payments in Nigeria via Providus Bank dynamic accounts.\n\n### How It Works\n\n1. **Initialize** — Call `POST /merchant/initialize` with the payment amount and your unique reference. You receive a Providus bank account number.\n2. **Customer Pays** — Share the account details with your customer. They make a bank transfer to the provided account.\n3. **Webhook** — When payment is received, Appia sends a webhook to your configured URL with the `collection.successful` event.\n4. **Verify** — Optionally call `GET /merchant/transaction/:ref` to confirm the payment status.\n\n### Authentication\n\nAll API requests require a Bearer token:\n```\nAuthorization: Bearer sk_live_<your_64_hex_char_key>\n```\n\nYour API key is provided during merchant onboarding. Keep it secret — treat it like a password.\n\n### Rate Limits\n\n- 100 requests per 60-second window\n- Rate limit headers are included in every response\n- HTTP 429 returned when limit is exceeded\n\n### Setup\n\n1. Import the environment file and set your `merchant_api_key`\n2. Set `base_url` to `https://api.appiawave.com` (or your staging URL)\n3. Set `webhook_receiver_url` to your webhook endpoint (for testing webhook payloads)\n\n---\n\n*Use this request to quickly verify your API key is working. A successful response means you are authenticated.*"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-RateLimit-Limit","value":"100"},{"key":"X-RateLimit-Remaining","value":"99"},{"key":"X-RateLimit-Reset","value":"1709136000"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"balance\": 0,\n    \"currency\": \"NGN\",\n    \"pending_payouts\": 0\n  }\n}"},{"id":"6b88d2ce-88ae-43aa-af30-35541419d928","name":"Error — Invalid API Key","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"## Appia Merchant Collection API\n\nThis API allows merchants to accept bank transfer payments in Nigeria via Providus Bank dynamic accounts.\n\n### How It Works\n\n1. **Initialize** — Call `POST /merchant/initialize` with the payment amount and your unique reference. You receive a Providus bank account number.\n2. **Customer Pays** — Share the account details with your customer. They make a bank transfer to the provided account.\n3. **Webhook** — When payment is received, Appia sends a webhook to your configured URL with the `collection.successful` event.\n4. **Verify** — Optionally call `GET /merchant/transaction/:ref` to confirm the payment status.\n\n### Authentication\n\nAll API requests require a Bearer token:\n```\nAuthorization: Bearer sk_live_<your_64_hex_char_key>\n```\n\nYour API key is provided during merchant onboarding. Keep it secret — treat it like a password.\n\n### Rate Limits\n\n- 100 requests per 60-second window\n- Rate limit headers are included in every response\n- HTTP 429 returned when limit is exceeded\n\n### Setup\n\n1. Import the environment file and set your `merchant_api_key`\n2. Set `base_url` to `https://api.appiawave.com` (or your staging URL)\n3. Set `webhook_receiver_url` to your webhook endpoint (for testing webhook payloads)\n\n---\n\n*Use this request to quickly verify your API key is working. A successful response means you are authenticated.*"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Invalid API key\"\n}"},{"id":"277483d2-8c08-4076-884f-62a80fd26279","name":"Error — Merchant Pending","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"## Appia Merchant Collection API\n\nThis API allows merchants to accept bank transfer payments in Nigeria via Providus Bank dynamic accounts.\n\n### How It Works\n\n1. **Initialize** — Call `POST /merchant/initialize` with the payment amount and your unique reference. You receive a Providus bank account number.\n2. **Customer Pays** — Share the account details with your customer. They make a bank transfer to the provided account.\n3. **Webhook** — When payment is received, Appia sends a webhook to your configured URL with the `collection.successful` event.\n4. **Verify** — Optionally call `GET /merchant/transaction/:ref` to confirm the payment status.\n\n### Authentication\n\nAll API requests require a Bearer token:\n```\nAuthorization: Bearer sk_live_<your_64_hex_char_key>\n```\n\nYour API key is provided during merchant onboarding. Keep it secret — treat it like a password.\n\n### Rate Limits\n\n- 100 requests per 60-second window\n- Rate limit headers are included in every response\n- HTTP 429 returned when limit is exceeded\n\n### Setup\n\n1. Import the environment file and set your `merchant_api_key`\n2. Set `base_url` to `https://api.appiawave.com` (or your staging URL)\n3. Set `webhook_receiver_url` to your webhook endpoint (for testing webhook payloads)\n\n---\n\n*Use this request to quickly verify your API key is working. A successful response means you are authenticated.*"},"status":"Forbidden","code":403,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Merchant account is pending activation\"\n}"}],"_postman_id":"1685e95a-21fe-476a-aa9c-c96977b3c3c2"}],"id":"4d773d53-7c6e-40c8-ab76-ba15dc6a4962","description":"<p>Setup instructions and authentication overview for the Appia Merchant Collection API.</p>\n","_postman_id":"4d773d53-7c6e-40c8-ab76-ba15dc6a4962","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}},{"name":"Collection API","item":[{"name":"Initialize Transaction","id":"30b5dc9a-3c8b-4f71-a835-0251cb52b3c5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 50000,\n  \"reference\": \"ORDER-2026-001\",\n  \"account_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"customer_name\": \"John Doe\",\n  \"description\": \"Payment for Invoice #001\",\n  \"split_code\": \"SPL_a7Bf3xK9\",\n  \"callback_url\": \"https://yoursite.com/webhooks/appia\",\n  \"metadata\": {\n    \"order_id\": \"ORD-12345\",\n    \"product\": \"Premium Plan\"\n  }\n}"},"url":"{{base_url}}/merchant/initialize","description":"<p>Initialize a collection transaction. This creates a Providus dynamic bank account that the customer can transfer to.</p>\n<h3 id=\"required-fields\">Required Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>amount</code></td>\n<td>number</td>\n<td>Amount in Naira (must be &gt; 0)</td>\n</tr>\n<tr>\n<td><code>reference</code></td>\n<td>string</td>\n<td>Your unique reference for this transaction</td>\n</tr>\n<tr>\n<td><code>account_name</code></td>\n<td>string</td>\n<td>Customer name for the bank account</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"optional-fields\">Optional Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>customer_email</code></td>\n<td>string</td>\n<td>Customer email address</td>\n</tr>\n<tr>\n<td><code>customer_name</code></td>\n<td>string</td>\n<td>Customer display name</td>\n</tr>\n<tr>\n<td><code>description</code></td>\n<td>string</td>\n<td>Payment description</td>\n</tr>\n<tr>\n<td><code>callback_url</code></td>\n<td>string</td>\n<td>Override webhook URL for this transaction</td>\n</tr>\n<tr>\n<td><code>metadata</code></td>\n<td>object</td>\n<td>Custom key-value data (returned in webhooks)</td>\n</tr>\n<tr>\n<td><code>split_code</code></td>\n<td>string</td>\n<td>Split group code (e.g. <code>SPL_a7Bf3xK9</code>) — routes payout to that split group's beneficiaries</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"notes\">Notes</h3>\n<ul>\n<li>The <code>reference</code> must be unique per merchant. Sending the same reference returns the existing transaction (idempotent).</li>\n<li>The dynamic account expires after <strong>30 minutes</strong>.</li>\n<li>The <code>account_name</code> is combined with the reference to form the Providus account name.</li>\n<li><strong>Split Code</strong>: Pass <code>split_code</code> to route the payout for this transaction to a specific split group. Transactions without a <code>split_code</code> will NOT be included in the daily 2 AM payout — funds stay in your merchant wallet. Create split groups via <code>POST /merchant/splits</code>.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","initialize"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"33a8e151-7ec1-4241-bc6b-8f13ee53be7c","name":"Success — Transaction Initialized","originalRequest":{"header":[]},"status":"Created","code":201,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"account_number\": \"9900123456\",\n    \"account_name\": \"John Doe/ORDER-2026-001\",\n    \"bank_name\": \"Providus Bank\",\n    \"amount\": 1200,\n    \"fee\": 200,\n    \"fee_bearer\": \"customer\",\n    \"expires_at\": \"2026-02-28T15:30:00.000Z\",\n    \"status\": \"initialized\"\n  }\n}"},{"id":"52f9e148-50ac-41df-a176-046edd7c4d74","name":"Success — Idempotent (duplicate reference)","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 50000,\n  \"reference\": \"ORDER-2026-001\",\n  \"account_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"customer_name\": \"John Doe\",\n  \"description\": \"Payment for Invoice #001\",\n  \"split_code\": \"SPL_a7Bf3xK9\",\n  \"callback_url\": \"https://yoursite.com/webhooks/appia\",\n  \"metadata\": {\n    \"order_id\": \"ORD-12345\",\n    \"product\": \"Premium Plan\"\n  }\n}"},"url":"{{base_url}}/merchant/initialize","description":"Initialize a collection transaction. This creates a Providus dynamic bank account that the customer can transfer to.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `amount` | number | Amount in Naira (must be > 0) |\n| `reference` | string | Your unique reference for this transaction |\n| `account_name` | string | Customer name for the bank account |\n\n### Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `customer_email` | string | Customer email address |\n| `customer_name` | string | Customer display name |\n| `description` | string | Payment description |\n| `callback_url` | string | Override webhook URL for this transaction |\n| `metadata` | object | Custom key-value data (returned in webhooks) |\n| `split_code` | string | Split group code (e.g. `SPL_a7Bf3xK9`) — routes payout to that split group's beneficiaries |\n\n### Notes\n\n- The `reference` must be unique per merchant. Sending the same reference returns the existing transaction (idempotent).\n- The dynamic account expires after **30 minutes**.\n- The `account_name` is combined with the reference to form the Providus account name.\n- **Split Code**: Pass `split_code` to route the payout for this transaction to a specific split group. Transactions without a `split_code` will NOT be included in the daily 2 AM payout — funds stay in your merchant wallet. Create split groups via `POST /merchant/splits`."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"account_number\": \"9900123456\",\n    \"account_name\": \"John Doe/ORDER-2026-001\",\n    \"bank_name\": \"Providus Bank\",\n    \"amount\": 50000,\n    \"split_code\": \"SPL_a7Bf3xK9\",\n    \"expires_at\": \"2026-02-28T15:30:00.000Z\",\n    \"status\": \"initialized\"\n  }\n}"},{"id":"f4f29f83-5ccb-4d27-a744-3d2885189111","name":"Error — Missing Required Fields","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 50000,\n  \"reference\": \"ORDER-2026-001\",\n  \"account_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"customer_name\": \"John Doe\",\n  \"description\": \"Payment for Invoice #001\",\n  \"split_code\": \"SPL_a7Bf3xK9\",\n  \"callback_url\": \"https://yoursite.com/webhooks/appia\",\n  \"metadata\": {\n    \"order_id\": \"ORD-12345\",\n    \"product\": \"Premium Plan\"\n  }\n}"},"url":"{{base_url}}/merchant/initialize","description":"Initialize a collection transaction. This creates a Providus dynamic bank account that the customer can transfer to.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `amount` | number | Amount in Naira (must be > 0) |\n| `reference` | string | Your unique reference for this transaction |\n| `account_name` | string | Customer name for the bank account |\n\n### Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `customer_email` | string | Customer email address |\n| `customer_name` | string | Customer display name |\n| `description` | string | Payment description |\n| `callback_url` | string | Override webhook URL for this transaction |\n| `metadata` | object | Custom key-value data (returned in webhooks) |\n| `split_code` | string | Split group code (e.g. `SPL_a7Bf3xK9`) — routes payout to that split group's beneficiaries |\n\n### Notes\n\n- The `reference` must be unique per merchant. Sending the same reference returns the existing transaction (idempotent).\n- The dynamic account expires after **30 minutes**.\n- The `account_name` is combined with the reference to form the Providus account name.\n- **Split Code**: Pass `split_code` to route the payout for this transaction to a specific split group. Transactions without a `split_code` will NOT be included in the daily 2 AM payout — funds stay in your merchant wallet. Create split groups via `POST /merchant/splits`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"amount must be a number greater than 0\"\n}"},{"id":"c031d706-072e-4056-ab3f-8f83a5cf4419","name":"Error — Feature Disabled","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 50000,\n  \"reference\": \"ORDER-2026-001\",\n  \"account_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"customer_name\": \"John Doe\",\n  \"description\": \"Payment for Invoice #001\",\n  \"split_code\": \"SPL_a7Bf3xK9\",\n  \"callback_url\": \"https://yoursite.com/webhooks/appia\",\n  \"metadata\": {\n    \"order_id\": \"ORD-12345\",\n    \"product\": \"Premium Plan\"\n  }\n}"},"url":"{{base_url}}/merchant/initialize","description":"Initialize a collection transaction. This creates a Providus dynamic bank account that the customer can transfer to.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `amount` | number | Amount in Naira (must be > 0) |\n| `reference` | string | Your unique reference for this transaction |\n| `account_name` | string | Customer name for the bank account |\n\n### Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `customer_email` | string | Customer email address |\n| `customer_name` | string | Customer display name |\n| `description` | string | Payment description |\n| `callback_url` | string | Override webhook URL for this transaction |\n| `metadata` | object | Custom key-value data (returned in webhooks) |\n| `split_code` | string | Split group code (e.g. `SPL_a7Bf3xK9`) — routes payout to that split group's beneficiaries |\n\n### Notes\n\n- The `reference` must be unique per merchant. Sending the same reference returns the existing transaction (idempotent).\n- The dynamic account expires after **30 minutes**.\n- The `account_name` is combined with the reference to form the Providus account name.\n- **Split Code**: Pass `split_code` to route the payout for this transaction to a specific split group. Transactions without a `split_code` will NOT be included in the daily 2 AM payout — funds stay in your merchant wallet. Create split groups via `POST /merchant/splits`."},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Merchant collection is currently disabled\"\n}"},{"id":"65a74d4c-d582-41af-b196-aa53c3929fd7","name":"Error — Providus Failure","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"amount\": 50000,\n  \"reference\": \"ORDER-2026-001\",\n  \"account_name\": \"John Doe\",\n  \"customer_email\": \"john@example.com\",\n  \"customer_name\": \"John Doe\",\n  \"description\": \"Payment for Invoice #001\",\n  \"split_code\": \"SPL_a7Bf3xK9\",\n  \"callback_url\": \"https://yoursite.com/webhooks/appia\",\n  \"metadata\": {\n    \"order_id\": \"ORD-12345\",\n    \"product\": \"Premium Plan\"\n  }\n}"},"url":"{{base_url}}/merchant/initialize","description":"Initialize a collection transaction. This creates a Providus dynamic bank account that the customer can transfer to.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `amount` | number | Amount in Naira (must be > 0) |\n| `reference` | string | Your unique reference for this transaction |\n| `account_name` | string | Customer name for the bank account |\n\n### Optional Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `customer_email` | string | Customer email address |\n| `customer_name` | string | Customer display name |\n| `description` | string | Payment description |\n| `callback_url` | string | Override webhook URL for this transaction |\n| `metadata` | object | Custom key-value data (returned in webhooks) |\n| `split_code` | string | Split group code (e.g. `SPL_a7Bf3xK9`) — routes payout to that split group's beneficiaries |\n\n### Notes\n\n- The `reference` must be unique per merchant. Sending the same reference returns the existing transaction (idempotent).\n- The dynamic account expires after **30 minutes**.\n- The `account_name` is combined with the reference to form the Providus account name.\n- **Split Code**: Pass `split_code` to route the payout for this transaction to a specific split group. Transactions without a `split_code` will NOT be included in the daily 2 AM payout — funds stay in your merchant wallet. Create split groups via `POST /merchant/splits`."},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Failed to create payment account. Please try again.\"\n}"}],"_postman_id":"30b5dc9a-3c8b-4f71-a835-0251cb52b3c5"},{"name":"Get Transaction Status","id":"a99ec765-00d2-467b-a60f-a88b91342812","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/transaction/:ref","description":"<p>Retrieve the current status and details of a collection transaction by your merchant reference.</p>\n<h3 id=\"transaction-statuses\">Transaction Statuses</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>initialized</code></td>\n<td>Dynamic account created, awaiting payment</td>\n</tr>\n<tr>\n<td><code>completed</code></td>\n<td>Full payment received and settled</td>\n</tr>\n<tr>\n<td><code>amount_mismatch</code></td>\n<td>Payment received but amount differs from expected</td>\n</tr>\n<tr>\n<td><code>expired</code></td>\n<td>No payment received within 30-minute window</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"response-fields\">Response Fields</h3>\n<ul>\n<li><code>source</code> — Sender's bank account details (populated after payment)</li>\n<li><code>fee_amount</code> — Platform fee deducted</li>\n<li><code>net_amount</code> — Amount credited to merchant wallet (after fees)</li>\n<li><code>metadata</code> — Your custom data from initialization</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","transaction",":ref"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"ff03405a-a838-4691-8a45-7674cc88a845","description":{"content":"<p>Your merchant reference used during initialization</p>\n","type":"text/plain"},"type":"any","value":"ORDER-2026-001","key":"ref"}]}},"response":[{"id":"db5e99c4-490b-45d0-b80b-0d0ffb1416b2","name":"Success — Completed Transaction","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/transaction/:ref","host":["{{base_url}}"],"path":["merchant","transaction",":ref"],"variable":[{"id":"ff03405a-a838-4691-8a45-7674cc88a845","key":"ref","value":"ORDER-2026-001","description":"Your merchant reference used during initialization"}]},"description":"Retrieve the current status and details of a collection transaction by your merchant reference.\n\n### Transaction Statuses\n\n| Status | Description |\n|--------|-------------|\n| `initialized` | Dynamic account created, awaiting payment |\n| `completed` | Full payment received and settled |\n| `amount_mismatch` | Payment received but amount differs from expected |\n| `expired` | No payment received within 30-minute window |\n\n### Response Fields\n\n- `source` — Sender's bank account details (populated after payment)\n- `fee_amount` — Platform fee deducted\n- `net_amount` — Amount credited to merchant wallet (after fees)\n- `metadata` — Your custom data from initialization"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"status\": \"completed\",\n    \"expected_amount\": 50000,\n    \"received_amount\": 50000,\n    \"fee_amount\": 750,\n    \"net_amount\": 49250,\n    \"customer_email\": \"john@example.com\",\n    \"customer_name\": \"John Doe\",\n    \"description\": \"Payment for Invoice #001\",\n    \"paid_at\": \"2026-02-28T15:05:00.000Z\",\n    \"expires_at\": \"2026-02-28T15:30:00.000Z\",\n    \"source\": {\n      \"account_number\": \"0123456789\",\n      \"account_name\": \"JOHN DOE\",\n      \"bank_name\": \"GTBank\"\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12345\",\n      \"product\": \"Premium Plan\"\n    },\n    \"created_at\": \"2026-02-28T15:00:00.000Z\"\n  }\n}"},{"id":"ae3088d0-a991-4103-b9f8-d8ee2f298954","name":"Success — Initialized (Awaiting Payment)","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/transaction/:ref","host":["{{base_url}}"],"path":["merchant","transaction",":ref"],"variable":[{"id":"ff03405a-a838-4691-8a45-7674cc88a845","key":"ref","value":"ORDER-2026-001","description":"Your merchant reference used during initialization"}]},"description":"Retrieve the current status and details of a collection transaction by your merchant reference.\n\n### Transaction Statuses\n\n| Status | Description |\n|--------|-------------|\n| `initialized` | Dynamic account created, awaiting payment |\n| `completed` | Full payment received and settled |\n| `amount_mismatch` | Payment received but amount differs from expected |\n| `expired` | No payment received within 30-minute window |\n\n### Response Fields\n\n- `source` — Sender's bank account details (populated after payment)\n- `fee_amount` — Platform fee deducted\n- `net_amount` — Amount credited to merchant wallet (after fees)\n- `metadata` — Your custom data from initialization"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"status\": \"initialized\",\n    \"expected_amount\": 50000,\n    \"received_amount\": null,\n    \"fee_amount\": null,\n    \"net_amount\": null,\n    \"customer_email\": \"john@example.com\",\n    \"customer_name\": \"John Doe\",\n    \"description\": \"Payment for Invoice #001\",\n    \"paid_at\": null,\n    \"expires_at\": \"2026-02-28T15:30:00.000Z\",\n    \"source\": {\n      \"account_number\": null,\n      \"account_name\": null,\n      \"bank_name\": null\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12345\",\n      \"product\": \"Premium Plan\"\n    },\n    \"created_at\": \"2026-02-28T15:00:00.000Z\"\n  }\n}"},{"id":"5ba4e428-eee7-4055-929b-a70dc3c6a22c","name":"Error — Not Found","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/transaction/:ref","host":["{{base_url}}"],"path":["merchant","transaction",":ref"],"variable":[{"id":"ff03405a-a838-4691-8a45-7674cc88a845","key":"ref","value":"ORDER-2026-001","description":"Your merchant reference used during initialization"}]},"description":"Retrieve the current status and details of a collection transaction by your merchant reference.\n\n### Transaction Statuses\n\n| Status | Description |\n|--------|-------------|\n| `initialized` | Dynamic account created, awaiting payment |\n| `completed` | Full payment received and settled |\n| `amount_mismatch` | Payment received but amount differs from expected |\n| `expired` | No payment received within 30-minute window |\n\n### Response Fields\n\n- `source` — Sender's bank account details (populated after payment)\n- `fee_amount` — Platform fee deducted\n- `net_amount` — Amount credited to merchant wallet (after fees)\n- `metadata` — Your custom data from initialization"},"status":"Not Found","code":404,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Transaction not found\"\n}"}],"_postman_id":"a99ec765-00d2-467b-a60f-a88b91342812"},{"name":"List Transactions","id":"5a9c0eee-e499-41fd-bf16-2cca212c1467","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/transactions?limit=25&offset=0","description":"<p>List all collection transactions for your merchant account with optional filters and pagination.</p>\n<h3 id=\"query-parameters\">Query Parameters</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Type</th>\n<th>Default</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>limit</code></td>\n<td>number</td>\n<td>50</td>\n<td>Results per page (max 100)</td>\n</tr>\n<tr>\n<td><code>offset</code></td>\n<td>number</td>\n<td>0</td>\n<td>Number of results to skip</td>\n</tr>\n<tr>\n<td><code>status</code></td>\n<td>string</td>\n<td>—</td>\n<td>Filter: <code>initialized</code>, <code>completed</code>, <code>amount_mismatch</code>, <code>expired</code></td>\n</tr>\n<tr>\n<td><code>start_date</code></td>\n<td>string</td>\n<td>—</td>\n<td>ISO 8601 date (inclusive)</td>\n</tr>\n<tr>\n<td><code>end_date</code></td>\n<td>string</td>\n<td>—</td>\n<td>ISO 8601 date (inclusive)</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","transactions"],"host":["{{base_url}}"],"query":[{"description":{"content":"<p>Results per page (default: 50, max: 100)</p>\n","type":"text/plain"},"key":"limit","value":"25"},{"description":{"content":"<p>Number of results to skip (default: 0)</p>\n","type":"text/plain"},"key":"offset","value":"0"},{"disabled":true,"description":{"content":"<p>Filter by status: initialized, completed, amount_mismatch, expired</p>\n","type":"text/plain"},"key":"status","value":""},{"disabled":true,"description":{"content":"<p>Filter from date (ISO 8601 format, e.g. 2026-02-01)</p>\n","type":"text/plain"},"key":"start_date","value":""},{"disabled":true,"description":{"content":"<p>Filter to date (ISO 8601 format, e.g. 2026-02-28)</p>\n","type":"text/plain"},"key":"end_date","value":""}],"variable":[]}},"response":[{"id":"6fb46205-c29d-454c-9934-7e795157a96a","name":"Success — Transaction List","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/transactions?limit=25&offset=0","host":["{{base_url}}"],"path":["merchant","transactions"],"query":[{"key":"limit","value":"25","description":"Results per page (default: 50, max: 100)"},{"key":"offset","value":"0","description":"Number of results to skip (default: 0)"},{"key":"status","value":"","description":"Filter by status: initialized, completed, amount_mismatch, expired","disabled":true},{"key":"start_date","value":"","description":"Filter from date (ISO 8601 format, e.g. 2026-02-01)","disabled":true},{"key":"end_date","value":"","description":"Filter to date (ISO 8601 format, e.g. 2026-02-28)","disabled":true}]},"description":"List all collection transactions for your merchant account with optional filters and pagination.\n\n### Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `limit` | number | 50 | Results per page (max 100) |\n| `offset` | number | 0 | Number of results to skip |\n| `status` | string | — | Filter: `initialized`, `completed`, `amount_mismatch`, `expired` |\n| `start_date` | string | — | ISO 8601 date (inclusive) |\n| `end_date` | string | — | ISO 8601 date (inclusive) |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"transactions\": [\n      {\n        \"id\": 1,\n        \"merchant_id\": \"MCH_JbsAv757ZrDgJZAT\",\n        \"initialization_ref\": \"ORDER-2026-001\",\n        \"internal_ref\": \"APM_x7Kf9Gh2mNpQ3R\",\n        \"status\": \"completed\",\n        \"expected_amount\": 50000,\n        \"received_amount\": 50000,\n        \"fee_amount\": 750,\n        \"net_amount\": 49250,\n        \"paid_at\": \"2026-02-28T15:05:00.000Z\",\n        \"created_at\": \"2026-02-28T15:00:00.000Z\"\n      },\n      {\n        \"id\": 2,\n        \"merchant_id\": \"MCH_JbsAv757ZrDgJZAT\",\n        \"initialization_ref\": \"ORDER-2026-002\",\n        \"internal_ref\": \"APM_mN3pQ7rS9tU1wX\",\n        \"status\": \"initialized\",\n        \"expected_amount\": 25000,\n        \"received_amount\": null,\n        \"fee_amount\": null,\n        \"net_amount\": null,\n        \"paid_at\": null,\n        \"created_at\": \"2026-02-28T16:00:00.000Z\"\n      }\n    ],\n    \"pagination\": {\n      \"currentPage\": 1,\n      \"totalPages\": 1,\n      \"totalRecords\": 2,\n      \"limit\": 25,\n      \"hasNext\": false,\n      \"hasPrev\": false\n    }\n  }\n}"}],"_postman_id":"5a9c0eee-e499-41fd-bf16-2cca212c1467"},{"name":"Get Balance","id":"b830dcbe-ece4-42fa-8db2-999e57848385","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"<p>Get your merchant wallet balance and any pending payout amounts.</p>\n<h3 id=\"response-fields\">Response Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>balance</code></td>\n<td>number</td>\n<td>Current wallet balance in Naira</td>\n</tr>\n<tr>\n<td><code>currency</code></td>\n<td>string</td>\n<td>Always <code>NGN</code></td>\n</tr>\n<tr>\n<td><code>pending_payouts</code></td>\n<td>number</td>\n<td>Total amount in pending/processing payouts</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","balance"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"b7ee0b47-eef5-4cc4-a082-ba3185b628d6","name":"Success — Balance","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/balance","description":"Get your merchant wallet balance and any pending payout amounts.\n\n### Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `balance` | number | Current wallet balance in Naira |\n| `currency` | string | Always `NGN` |\n| `pending_payouts` | number | Total amount in pending/processing payouts |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"balance\": 1250000,\n    \"currency\": \"NGN\",\n    \"pending_payouts\": 50000\n  }\n}"}],"_postman_id":"b830dcbe-ece4-42fa-8db2-999e57848385"},{"name":"List Payouts","id":"d908a038-048e-4a0e-8502-73cb79130da9","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/payouts?limit=25&offset=0","description":"<p>List payout batches for your merchant account. Payouts are processed daily at 2:00 AM WAT.</p>\n<h3 id=\"payout-statuses\">Payout Statuses</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>processing</code></td>\n<td>Payout batch is being executed</td>\n</tr>\n<tr>\n<td><code>completed</code></td>\n<td>All transfers successful</td>\n</tr>\n<tr>\n<td><code>partial_failure</code></td>\n<td>Some transfers failed (will be retried)</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","payouts"],"host":["{{base_url}}"],"query":[{"description":{"content":"<p>Results per page (default: 50, max: 100)</p>\n","type":"text/plain"},"key":"limit","value":"25"},{"description":{"content":"<p>Number of results to skip (default: 0)</p>\n","type":"text/plain"},"key":"offset","value":"0"},{"disabled":true,"description":{"content":"<p>Filter: pending, processing, completed, partial_failure</p>\n","type":"text/plain"},"key":"status","value":""},{"disabled":true,"description":{"content":"<p>Filter from date (ISO 8601)</p>\n","type":"text/plain"},"key":"start_date","value":""},{"disabled":true,"description":{"content":"<p>Filter to date (ISO 8601)</p>\n","type":"text/plain"},"key":"end_date","value":""}],"variable":[]}},"response":[{"id":"7c2840e5-817a-40d5-9683-200123fe71a3","name":"Success — Payout List","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/payouts?limit=25&offset=0","host":["{{base_url}}"],"path":["merchant","payouts"],"query":[{"key":"limit","value":"25","description":"Results per page (default: 50, max: 100)"},{"key":"offset","value":"0","description":"Number of results to skip (default: 0)"},{"key":"status","value":"","description":"Filter: pending, processing, completed, partial_failure","disabled":true},{"key":"start_date","value":"","description":"Filter from date (ISO 8601)","disabled":true},{"key":"end_date","value":"","description":"Filter to date (ISO 8601)","disabled":true}]},"description":"List payout batches for your merchant account. Payouts are processed daily at 2:00 AM WAT.\n\n### Payout Statuses\n\n| Status | Description |\n|--------|-------------|\n| `processing` | Payout batch is being executed |\n| `completed` | All transfers successful |\n| `partial_failure` | Some transfers failed (will be retried) |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"payouts\": [\n      {\n        \"id\": 1,\n        \"merchant_id\": \"MCH_JbsAv757ZrDgJZAT\",\n        \"batch_ref\": \"PYT_20260227_MCH_JbsAv757ZrDgJZAT\",\n        \"payout_date\": \"2026-02-27\",\n        \"status\": \"completed\",\n        \"total_collected\": 500000,\n        \"total_fees\": 7500,\n        \"total_transfer_fees\": 110,\n        \"total_payout\": 492390,\n        \"total_net\": 492500,\n        \"transaction_count\": 10,\n        \"created_at\": \"2026-02-28T01:00:00.000Z\",\n        \"completed_at\": \"2026-02-28T01:05:00.000Z\"\n      }\n    ],\n    \"pagination\": {\n      \"currentPage\": 1,\n      \"totalPages\": 1,\n      \"totalRecords\": 1,\n      \"limit\": 25,\n      \"hasNext\": false,\n      \"hasPrev\": false\n    }\n  }\n}"}],"_postman_id":"d908a038-048e-4a0e-8502-73cb79130da9"},{"name":"Get Payout Details","id":"513c3574-be79-4085-82a6-dd4d5a430726","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/payout/:batch_ref","description":"<p>Get detailed information about a specific payout batch, including individual transfer items and their statuses.</p>\n<h3 id=\"payout-item-statuses\">Payout Item Statuses</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>pending</code></td>\n<td>Transfer queued</td>\n</tr>\n<tr>\n<td><code>success</code></td>\n<td>NIP transfer completed</td>\n</tr>\n<tr>\n<td><code>failed</code></td>\n<td>Transfer failed (will be retried up to 8 times)</td>\n</tr>\n<tr>\n<td><code>refunded</code></td>\n<td>All retries exhausted, amount refunded to merchant wallet</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","payout",":batch_ref"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"5b1517e0-36c3-4608-bbd6-6840a82e617e","description":{"content":"<p>The payout batch reference</p>\n","type":"text/plain"},"type":"any","value":"PYT_20260227_MCH_JbsAv757ZrDgJZAT","key":"batch_ref"}]}},"response":[{"id":"06d7e969-7422-4640-8731-26c9fae560b1","name":"Success — Payout Details","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/payout/:batch_ref","host":["{{base_url}}"],"path":["merchant","payout",":batch_ref"],"variable":[{"id":"5b1517e0-36c3-4608-bbd6-6840a82e617e","key":"batch_ref","value":"PYT_20260227_MCH_JbsAv757ZrDgJZAT","description":"The payout batch reference"}]},"description":"Get detailed information about a specific payout batch, including individual transfer items and their statuses.\n\n### Payout Item Statuses\n\n| Status | Description |\n|--------|-------------|\n| `pending` | Transfer queued |\n| `success` | NIP transfer completed |\n| `failed` | Transfer failed (will be retried up to 8 times) |\n| `refunded` | All retries exhausted, amount refunded to merchant wallet |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"batch_ref\": \"PYT_20260227_MCH_JbsAv757ZrDgJZAT\",\n    \"payout_date\": \"2026-02-27\",\n    \"status\": \"completed\",\n    \"total_collected\": 500000,\n    \"total_fees\": 7500,\n    \"total_transfer_fees\": 110,\n    \"total_payout\": 492390,\n    \"total_net\": 492500,\n    \"transaction_count\": 10,\n    \"items\": [\n      {\n        \"id\": 1,\n        \"account_name\": \"Operations Account\",\n        \"account_number\": \"0123456789\",\n        \"bank_code\": \"057\",\n        \"bank_name\": \"Zenith Bank\",\n        \"amount\": 344673,\n        \"transfer_fee\": 55,\n        \"transfer_ref\": \"MPO_x7Kf9Gh2mNpQ3R\",\n        \"status\": \"success\"\n      },\n      {\n        \"id\": 2,\n        \"account_name\": \"Revenue Account\",\n        \"account_number\": \"9876543210\",\n        \"bank_code\": \"058\",\n        \"bank_name\": \"GTBank\",\n        \"amount\": 147717,\n        \"transfer_fee\": 55,\n        \"transfer_ref\": \"MPO_mN3pQ7rS9tU1wX\",\n        \"status\": \"success\"\n      }\n    ],\n    \"created_at\": \"2026-02-28T01:00:00.000Z\",\n    \"completed_at\": \"2026-02-28T01:05:00.000Z\"\n  }\n}"},{"id":"051e902c-2967-4a3f-80ab-9cef2696ef44","name":"Error — Not Found","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{base_url}}/merchant/payout/:batch_ref","host":["{{base_url}}"],"path":["merchant","payout",":batch_ref"],"variable":[{"id":"5b1517e0-36c3-4608-bbd6-6840a82e617e","key":"batch_ref","value":"PYT_20260227_MCH_JbsAv757ZrDgJZAT","description":"The payout batch reference"}]},"description":"Get detailed information about a specific payout batch, including individual transfer items and their statuses.\n\n### Payout Item Statuses\n\n| Status | Description |\n|--------|-------------|\n| `pending` | Transfer queued |\n| `success` | NIP transfer completed |\n| `failed` | Transfer failed (will be retried up to 8 times) |\n| `refunded` | All retries exhausted, amount refunded to merchant wallet |"},"status":"Not Found","code":404,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Payout batch not found\"\n}"}],"_postman_id":"513c3574-be79-4085-82a6-dd4d5a430726"},{"name":"Process Payout","id":"c895bd74-cd59-4cef-90a6-322e355817b6","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n    \"dry_run\": true\n}","options":{"raw":{"language":"json"}}},"url":"{{base_url}}/merchant/payouts/trigger","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","payouts","trigger"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"c895bd74-cd59-4cef-90a6-322e355817b6"}],"id":"71b3f567-16f8-42c5-b35f-ae5ee2893157","description":"<p>Core merchant-facing endpoints for initializing transactions, checking status, viewing balances, and managing payouts.</p>\n","_postman_id":"71b3f567-16f8-42c5-b35f-ae5ee2893157","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}},{"name":"Split Management","item":[{"name":"List Split Groups","id":"ade7fd99-0463-47f8-812c-da487ab2acc2","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/splits","description":"<p>List all active split groups for your merchant account. Each group includes its beneficiaries and their split configuration.</p>\n<h3 id=\"response-fields\">Response Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>split_code</code></td>\n<td>string</td>\n<td>Unique split group code (e.g., <code>SPL_a7Bf3xK9</code>)</td>\n</tr>\n<tr>\n<td><code>label</code></td>\n<td>string</td>\n<td>Display name for the group</td>\n</tr>\n<tr>\n<td><code>split_type</code></td>\n<td>string</td>\n<td><code>percentage</code> or <code>fixed</code></td>\n</tr>\n<tr>\n<td><code>beneficiaries</code></td>\n<td>array</td>\n<td>List of beneficiary accounts and their split values</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","splits"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"f105f7e1-1c15-415f-a708-2184d7ff3145","name":"Success — Split Groups","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/splits","description":"List all active split groups for your merchant account. Each group includes its beneficiaries and their split configuration.\n\n### Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `split_code` | string | Unique split group code (e.g., `SPL_a7Bf3xK9`) |\n| `label` | string | Display name for the group |\n| `split_type` | string | `percentage` or `fixed` |\n| `beneficiaries` | array | List of beneficiary accounts and their split values |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 1,\n      \"split_code\": \"SPL_a7Bf3xK9\",\n      \"label\": \"Operations Split\",\n      \"split_type\": \"percentage\",\n      \"is_active\": 1,\n      \"created_at\": \"2026-02-28T10:00:00.000Z\",\n      \"beneficiaries\": [\n        {\n          \"id\": 1,\n          \"label\": \"Operations Account\",\n          \"bank_code\": \"057\",\n          \"bank_name\": \"Zenith Bank\",\n          \"account_number\": \"0123456789\",\n          \"account_name\": \"ACME OPERATIONS LTD\",\n          \"split_value\": 70\n        },\n        {\n          \"id\": 2,\n          \"label\": \"Revenue Account\",\n          \"bank_code\": \"058\",\n          \"bank_name\": \"GTBank\",\n          \"account_number\": \"9876543210\",\n          \"account_name\": \"ACME REVENUE LTD\",\n          \"split_value\": 30\n        }\n      ]\n    }\n  ]\n}"}],"_postman_id":"ade7fd99-0463-47f8-812c-da487ab2acc2"},{"name":"Create Split Group","id":"64d65fdc-84fb-464a-84fe-94ff00a47704","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Operations Split\",\n  \"split_type\": \"percentage\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Operations Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 70\n    },\n    {\n      \"label\": \"Revenue Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 30\n    }\n  ]\n}"},"url":"{{base_url}}/merchant/splits","description":"<p>Create a new split group with one or more beneficiaries. All bank accounts are NIP-verified before the group is saved.</p>\n<h3 id=\"required-fields\">Required Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>label</code></td>\n<td>string</td>\n<td>Display name for the split group</td>\n</tr>\n<tr>\n<td><code>split_type</code></td>\n<td>string</td>\n<td><code>percentage</code> or <code>fixed</code></td>\n</tr>\n<tr>\n<td><code>beneficiaries</code></td>\n<td>array</td>\n<td>At least one beneficiary</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"beneficiary-fields\">Beneficiary Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>label</code></td>\n<td>string</td>\n<td>Display name for the beneficiary</td>\n</tr>\n<tr>\n<td><code>bank_code</code></td>\n<td>string</td>\n<td>Bank code (from <code>GET /merchant/banks</code>)</td>\n</tr>\n<tr>\n<td><code>account_number</code></td>\n<td>string</td>\n<td>10-digit NUBAN account number</td>\n</tr>\n<tr>\n<td><code>split_value</code></td>\n<td>number</td>\n<td>Percentage (0-100) or fixed amount in Naira</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"validation-rules\">Validation Rules</h3>\n<ul>\n<li>For <code>percentage</code> type: total of all <code>split_value</code> must be ≤ 100</li>\n<li>All bank accounts are verified via NIP before saving</li>\n<li>If any account verification fails, the entire request is rejected</li>\n<li><code>split_type</code> cannot be changed after creation</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","splits"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"d0eee53b-7e7a-448f-a902-3f86e938f9f7","name":"Success — Split Group Created","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Operations Split\",\n  \"split_type\": \"percentage\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Operations Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 70\n    },\n    {\n      \"label\": \"Revenue Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 30\n    }\n  ]\n}"},"url":"{{base_url}}/merchant/splits","description":"Create a new split group with one or more beneficiaries. All bank accounts are NIP-verified before the group is saved.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the split group |\n| `split_type` | string | `percentage` or `fixed` |\n| `beneficiaries` | array | At least one beneficiary |\n\n### Beneficiary Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the beneficiary |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |\n| `account_number` | string | 10-digit NUBAN account number |\n| `split_value` | number | Percentage (0-100) or fixed amount in Naira |\n\n### Validation Rules\n\n- For `percentage` type: total of all `split_value` must be ≤ 100\n- All bank accounts are verified via NIP before saving\n- If any account verification fails, the entire request is rejected\n- `split_type` cannot be changed after creation"},"status":"Created","code":201,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"id\": 1,\n    \"split_code\": \"SPL_a7Bf3xK9\",\n    \"label\": \"Operations Split\",\n    \"split_type\": \"percentage\",\n    \"beneficiaries\": [\n      {\n        \"id\": 1,\n        \"label\": \"Operations Account\",\n        \"bank_code\": \"057\",\n        \"bank_name\": \"Zenith Bank\",\n        \"account_number\": \"0123456789\",\n        \"account_name\": \"ACME OPERATIONS LTD\",\n        \"split_value\": 70\n      },\n      {\n        \"id\": 2,\n        \"label\": \"Revenue Account\",\n        \"bank_code\": \"058\",\n        \"bank_name\": \"GTBank\",\n        \"account_number\": \"9876543210\",\n        \"account_name\": \"ACME REVENUE LTD\",\n        \"split_value\": 30\n      }\n    ]\n  }\n}"},{"id":"bc1a69a0-135e-4827-9a00-64db77ec2fd9","name":"Error — Validation Failed","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Operations Split\",\n  \"split_type\": \"percentage\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Operations Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 70\n    },\n    {\n      \"label\": \"Revenue Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 30\n    }\n  ]\n}"},"url":"{{base_url}}/merchant/splits","description":"Create a new split group with one or more beneficiaries. All bank accounts are NIP-verified before the group is saved.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the split group |\n| `split_type` | string | `percentage` or `fixed` |\n| `beneficiaries` | array | At least one beneficiary |\n\n### Beneficiary Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the beneficiary |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |\n| `account_number` | string | 10-digit NUBAN account number |\n| `split_value` | number | Percentage (0-100) or fixed amount in Naira |\n\n### Validation Rules\n\n- For `percentage` type: total of all `split_value` must be ≤ 100\n- All bank accounts are verified via NIP before saving\n- If any account verification fails, the entire request is rejected\n- `split_type` cannot be changed after creation"},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Percentage total exceeds 100% (got 110%)\"\n}"},{"id":"e278c2ea-92b8-4c7c-898c-b006d1fbd7b7","name":"Error — Account Verification Failed","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Operations Split\",\n  \"split_type\": \"percentage\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Operations Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 70\n    },\n    {\n      \"label\": \"Revenue Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 30\n    }\n  ]\n}"},"url":"{{base_url}}/merchant/splits","description":"Create a new split group with one or more beneficiaries. All bank accounts are NIP-verified before the group is saved.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the split group |\n| `split_type` | string | `percentage` or `fixed` |\n| `beneficiaries` | array | At least one beneficiary |\n\n### Beneficiary Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | string | Display name for the beneficiary |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |\n| `account_number` | string | 10-digit NUBAN account number |\n| `split_value` | number | Percentage (0-100) or fixed amount in Naira |\n\n### Validation Rules\n\n- For `percentage` type: total of all `split_value` must be ≤ 100\n- All bank accounts are verified via NIP before saving\n- If any account verification fails, the entire request is rejected\n- `split_type` cannot be changed after creation"},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Account verification failed for 0123456789\"\n}"}],"_postman_id":"64d65fdc-84fb-464a-84fe-94ff00a47704"},{"name":"Update Split Group","id":"90a97a7e-eb2c-4448-8ca3-5c46673f1f95","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Updated Operations Split\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Main Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 60\n    },\n    {\n      \"label\": \"Secondary Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 25\n    },\n    {\n      \"label\": \"Savings Account\",\n      \"bank_code\": \"011\",\n      \"account_number\": \"1122334455\",\n      \"split_value\": 15\n    }\n  ]\n}"},"url":"{{base_url}}/merchant/splits/:code","description":"<p>Update an existing split group. You can update the label and/or replace all beneficiaries.</p>\n<h3 id=\"update-behavior\">Update Behavior</h3>\n<ul>\n<li>If <code>label</code> is provided, the group label is updated</li>\n<li>If <code>beneficiaries</code> is provided, <strong>all existing beneficiaries are replaced</strong> (full replacement, not partial update)</li>\n<li><code>split_type</code> cannot be changed after creation</li>\n<li>All new bank accounts are NIP-verified before saving</li>\n<li>Updates take effect at the next payout — already-batched transactions are not affected</li>\n</ul>\n<h3 id=\"fields\">Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>label</code></td>\n<td>string</td>\n<td>No</td>\n<td>New display name</td>\n</tr>\n<tr>\n<td><code>beneficiaries</code></td>\n<td>array</td>\n<td>No</td>\n<td>Full replacement list of beneficiaries</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","splits",":code"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"671f3c4f-b728-4d01-b3b6-72d35f3910a5","description":{"content":"<p>The split group code</p>\n","type":"text/plain"},"type":"any","value":"SPL_a7Bf3xK9","key":"code"}]}},"response":[{"id":"d383c06f-e8e0-46e0-9340-a5dac3678009","name":"Success — Split Group Updated","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Updated Operations Split\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Main Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 60\n    },\n    {\n      \"label\": \"Secondary Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 25\n    },\n    {\n      \"label\": \"Savings Account\",\n      \"bank_code\": \"011\",\n      \"account_number\": \"1122334455\",\n      \"split_value\": 15\n    }\n  ]\n}"},"url":{"raw":"{{base_url}}/merchant/splits/:code","host":["{{base_url}}"],"path":["merchant","splits",":code"],"variable":[{"id":"671f3c4f-b728-4d01-b3b6-72d35f3910a5","key":"code","value":"SPL_a7Bf3xK9","description":"The split group code"}]},"description":"Update an existing split group. You can update the label and/or replace all beneficiaries.\n\n### Update Behavior\n\n- If `label` is provided, the group label is updated\n- If `beneficiaries` is provided, **all existing beneficiaries are replaced** (full replacement, not partial update)\n- `split_type` cannot be changed after creation\n- All new bank accounts are NIP-verified before saving\n- Updates take effect at the next payout — already-batched transactions are not affected\n\n### Fields\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `label` | string | No | New display name |\n| `beneficiaries` | array | No | Full replacement list of beneficiaries |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"id\": 1,\n    \"split_code\": \"SPL_a7Bf3xK9\",\n    \"label\": \"Updated Operations Split\",\n    \"split_type\": \"percentage\",\n    \"beneficiaries\": [\n      {\n        \"id\": 5,\n        \"label\": \"Main Account\",\n        \"bank_code\": \"057\",\n        \"bank_name\": \"Zenith Bank\",\n        \"account_number\": \"0123456789\",\n        \"account_name\": \"ACME OPERATIONS LTD\",\n        \"split_value\": 60\n      },\n      {\n        \"id\": 6,\n        \"label\": \"Secondary Account\",\n        \"bank_code\": \"058\",\n        \"bank_name\": \"GTBank\",\n        \"account_number\": \"9876543210\",\n        \"account_name\": \"ACME REVENUE LTD\",\n        \"split_value\": 25\n      },\n      {\n        \"id\": 7,\n        \"label\": \"Savings Account\",\n        \"bank_code\": \"011\",\n        \"bank_name\": \"First Bank\",\n        \"account_number\": \"1122334455\",\n        \"account_name\": \"ACME SAVINGS LTD\",\n        \"split_value\": 15\n      }\n    ]\n  }\n}"},{"id":"5c5e7cd8-2e94-4304-b0df-3d30fdb4512e","name":"Error — Not Found","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"label\": \"Updated Operations Split\",\n  \"beneficiaries\": [\n    {\n      \"label\": \"Main Account\",\n      \"bank_code\": \"057\",\n      \"account_number\": \"0123456789\",\n      \"split_value\": 60\n    },\n    {\n      \"label\": \"Secondary Account\",\n      \"bank_code\": \"058\",\n      \"account_number\": \"9876543210\",\n      \"split_value\": 25\n    },\n    {\n      \"label\": \"Savings Account\",\n      \"bank_code\": \"011\",\n      \"account_number\": \"1122334455\",\n      \"split_value\": 15\n    }\n  ]\n}"},"url":{"raw":"{{base_url}}/merchant/splits/:code","host":["{{base_url}}"],"path":["merchant","splits",":code"],"variable":[{"id":"671f3c4f-b728-4d01-b3b6-72d35f3910a5","key":"code","value":"SPL_a7Bf3xK9","description":"The split group code"}]},"description":"Update an existing split group. You can update the label and/or replace all beneficiaries.\n\n### Update Behavior\n\n- If `label` is provided, the group label is updated\n- If `beneficiaries` is provided, **all existing beneficiaries are replaced** (full replacement, not partial update)\n- `split_type` cannot be changed after creation\n- All new bank accounts are NIP-verified before saving\n- Updates take effect at the next payout — already-batched transactions are not affected\n\n### Fields\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `label` | string | No | New display name |\n| `beneficiaries` | array | No | Full replacement list of beneficiaries |"},"status":"Not Found","code":404,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Split group not found\"\n}"}],"_postman_id":"90a97a7e-eb2c-4448-8ca3-5c46673f1f95"},{"name":"Deactivate Split Group","id":"ef5fbf71-1adb-41ac-a615-4bdb2b4aff26","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"{{base_url}}/merchant/splits/:code","description":"<p>Deactivate (soft-delete) a split group and all its beneficiary configs.</p>\n<h3 id=\"behavior\">Behavior</h3>\n<ul>\n<li>The group and all its configs are marked as inactive (<code>is_active = 0</code>)</li>\n<li>Existing transaction references to this <code>split_code</code> are preserved for historical payout records</li>\n<li>Already-batched transactions are not affected</li>\n<li>Future transactions using this <code>split_code</code> will be rejected during initialization</li>\n<li>This action is <strong>not reversible</strong> via API — contact admin to reactivate</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","splits",":code"],"host":["{{base_url}}"],"query":[],"variable":[{"id":"65cf96c4-6c75-4ebc-a4a0-0a6295956b4b","description":{"content":"<p>The split group code to deactivate</p>\n","type":"text/plain"},"type":"any","value":"SPL_a7Bf3xK9","key":"code"}]}},"response":[{"id":"961b279c-c533-4963-bfa8-58220fed181c","name":"Success — Split Group Deactivated","originalRequest":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/merchant/splits/:code","host":["{{base_url}}"],"path":["merchant","splits",":code"],"variable":[{"id":"65cf96c4-6c75-4ebc-a4a0-0a6295956b4b","key":"code","value":"SPL_a7Bf3xK9","description":"The split group code to deactivate"}]},"description":"Deactivate (soft-delete) a split group and all its beneficiary configs.\n\n### Behavior\n\n- The group and all its configs are marked as inactive (`is_active = 0`)\n- Existing transaction references to this `split_code` are preserved for historical payout records\n- Already-batched transactions are not affected\n- Future transactions using this `split_code` will be rejected during initialization\n- This action is **not reversible** via API — contact admin to reactivate"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"message\": \"Split group deactivated\"\n}"},{"id":"42b0de38-ced0-46ae-b57b-0f321867281a","name":"Error — Not Found","originalRequest":{"method":"DELETE","header":[],"url":{"raw":"{{base_url}}/merchant/splits/:code","host":["{{base_url}}"],"path":["merchant","splits",":code"],"variable":[{"id":"65cf96c4-6c75-4ebc-a4a0-0a6295956b4b","key":"code","value":"SPL_a7Bf3xK9","description":"The split group code to deactivate"}]},"description":"Deactivate (soft-delete) a split group and all its beneficiary configs.\n\n### Behavior\n\n- The group and all its configs are marked as inactive (`is_active = 0`)\n- Existing transaction references to this `split_code` are preserved for historical payout records\n- Already-batched transactions are not affected\n- Future transactions using this `split_code` will be rejected during initialization\n- This action is **not reversible** via API — contact admin to reactivate"},"status":"Not Found","code":404,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Split group not found\"\n}"}],"_postman_id":"ef5fbf71-1adb-41ac-a615-4bdb2b4aff26"},{"name":"List Banks","id":"cb724688-a109-4ebe-93d7-15d1b2cbca0f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"{{base_url}}/merchant/banks","description":"<p>Get the list of Nigerian banks supported for NIP transfers. Use the <code>code</code> field when creating split groups or resolving accounts.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns an array of <code>{ code, name }</code> objects representing all supported banks.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","banks"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"521f1833-7e96-4c7c-b16e-4b2615b77b82","name":"Success — Bank List","originalRequest":{"method":"GET","header":[],"url":"{{base_url}}/merchant/banks","description":"Get the list of Nigerian banks supported for NIP transfers. Use the `code` field when creating split groups or resolving accounts.\n\n### Response\n\nReturns an array of `{ code, name }` objects representing all supported banks."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": [\n    { \"code\": \"011\", \"name\": \"First Bank\" },\n    { \"code\": \"057\", \"name\": \"Zenith Bank\" },\n    { \"code\": \"058\", \"name\": \"GTBank\" },\n    { \"code\": \"044\", \"name\": \"Access Bank\" },\n    { \"code\": \"033\", \"name\": \"United Bank for Africa\" }\n  ]\n}"}],"_postman_id":"cb724688-a109-4ebe-93d7-15d1b2cbca0f"},{"name":"Resolve Account","id":"7c6120b9-0aed-4184-a809-0a2ef352e571","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"account_number\": \"0123456789\",\n  \"bank_code\": \"057\"\n}"},"url":"{{base_url}}/merchant/banks/resolve","description":"<p>Verify a bank account via NIP (Nigeria Inter-bank Payment). Returns the account holder's name if the account is valid.</p>\n<p>Use this to verify accounts before adding them to a split group.</p>\n<h3 id=\"required-fields\">Required Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>account_number</code></td>\n<td>string</td>\n<td>10-digit NUBAN account number</td>\n</tr>\n<tr>\n<td><code>bank_code</code></td>\n<td>string</td>\n<td>Bank code (from <code>GET /merchant/banks</code>)</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}},"urlObject":{"path":["merchant","banks","resolve"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"2535fbb5-770d-46df-a520-adfd0c34a9e1","name":"Success — Account Resolved","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"account_number\": \"0123456789\",\n  \"bank_code\": \"057\"\n}"},"url":"{{base_url}}/merchant/banks/resolve","description":"Verify a bank account via NIP (Nigeria Inter-bank Payment). Returns the account holder's name if the account is valid.\n\nUse this to verify accounts before adding them to a split group.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `account_number` | string | 10-digit NUBAN account number |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": true,\n  \"data\": {\n    \"account_name\": \"ACME OPERATIONS LTD\",\n    \"account_number\": \"0123456789\",\n    \"bank_code\": \"057\"\n  }\n}"},{"id":"85edc89f-f617-422e-bd23-2b26d1161c8c","name":"Error — Account Not Found","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"account_number\": \"0123456789\",\n  \"bank_code\": \"057\"\n}"},"url":"{{base_url}}/merchant/banks/resolve","description":"Verify a bank account via NIP (Nigeria Inter-bank Payment). Returns the account holder's name if the account is valid.\n\nUse this to verify accounts before adding them to a split group.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `account_number` | string | 10-digit NUBAN account number |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |"},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"Account verification failed\"\n}"},{"id":"61f1d477-80d8-42f3-9e5f-464200d762f1","name":"Error — Missing Fields","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"account_number\": \"0123456789\",\n  \"bank_code\": \"057\"\n}"},"url":"{{base_url}}/merchant/banks/resolve","description":"Verify a bank account via NIP (Nigeria Inter-bank Payment). Returns the account holder's name if the account is valid.\n\nUse this to verify accounts before adding them to a split group.\n\n### Required Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `account_number` | string | 10-digit NUBAN account number |\n| `bank_code` | string | Bank code (from `GET /merchant/banks`) |"},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"success\": false,\n  \"message\": \"account_number and bank_code are required\"\n}"}],"_postman_id":"7c6120b9-0aed-4184-a809-0a2ef352e571"}],"id":"f4daa0df-7998-4411-bc75-37db903eacec","description":"<p>Manage split groups for routing payouts to multiple beneficiaries. Each split group has a <code>split_code</code> (e.g., <code>SPL_a7Bf3xK9</code>) that you pass when initializing a transaction to determine how the payout is distributed.</p>\n<h3 id=\"how-splits-work\">How Splits Work</h3>\n<ol>\n<li><strong>Create a split group</strong> with one or more beneficiaries and their share (percentage or fixed amount)</li>\n<li><strong>Pass <code>split_code</code></strong> when initializing a transaction</li>\n<li>At <strong>2 AM daily</strong>, the cron job processes all completed transactions with split codes and distributes payouts to the configured beneficiaries</li>\n<li>Transactions <strong>without</strong> a <code>split_code</code> are NOT auto-paid out — funds remain in your merchant wallet</li>\n</ol>\n<h3 id=\"split-types\">Split Types</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>percentage</code></td>\n<td>Each beneficiary receives a percentage of the net amount. Total must be ≤ 100%</td>\n</tr>\n<tr>\n<td><code>fixed</code></td>\n<td>Each beneficiary receives a fixed amount per transaction</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"nip-verification\">NIP Verification</h3>\n<p>All bank accounts are verified via NIP (Nigeria Inter-bank Payment) before being saved. Use the <strong>Resolve Account</strong> endpoint to verify accounts before creating a split group.</p>\n","_postman_id":"f4daa0df-7998-4411-bc75-37db903eacec","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}},{"name":"Webhook Reference","item":[{"name":"collection.successful","id":"01f7cabb-7df8-4fcf-afe6-e74dba7d2c84","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"noauth","isInherited":false},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Appia-Signature","value":"a1b2c3d4e5f6...your_hmac_sha512_signature...abcdef1234567890","description":"<p>HMAC-SHA512 hex digest of the request body using your webhook secret</p>\n"},{"key":"X-Appia-Event","value":"collection.successful"},{"key":"X-Appia-Delivery-Id","value":"12345"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"collection.successful\",\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"status\": \"completed\",\n    \"expected_amount\": 50000,\n    \"received_amount\": 50000,\n    \"fee_amount\": 750,\n    \"net_amount\": 49250,\n    \"paid_at\": \"2026-02-28T15:05:00.000Z\",\n    \"source\": {\n      \"account_number\": \"0123456789\",\n      \"account_name\": \"JOHN DOE\",\n      \"bank_name\": \"GTBank\"\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12345\",\n      \"product\": \"Premium Plan\"\n    }\n  }\n}"},"url":"{{webhook_receiver_url}}","description":"<h2 id=\"collectionsuccessful\">collection.successful</h2>\n<p>Sent when a customer's bank transfer is received and the full expected amount (or more) is settled to your merchant wallet.</p>\n<h3 id=\"when-this-fires\">When This Fires</h3>\n<ul>\n<li><p>Customer transfers the exact amount or more to the Providus dynamic account</p>\n</li>\n<li><p>Funds are credited to your merchant wallet (minus fees)</p>\n</li>\n<li><p>Fee is deducted and credited to the platform fee wallet</p>\n</li>\n</ul>\n<h3 id=\"key-fields\">Key Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>reference</code></td>\n<td>Your merchant reference from initialization</td>\n</tr>\n<tr>\n<td><code>internal_reference</code></td>\n<td>Appia's internal reference</td>\n</tr>\n<tr>\n<td><code>expected_amount</code></td>\n<td>Amount you requested</td>\n</tr>\n<tr>\n<td><code>received_amount</code></td>\n<td>Amount actually received from the bank</td>\n</tr>\n<tr>\n<td><code>fee_amount</code></td>\n<td>Platform fee deducted</td>\n</tr>\n<tr>\n<td><code>net_amount</code></td>\n<td>Amount credited to your wallet</td>\n</tr>\n<tr>\n<td><code>source</code></td>\n<td>Sender's bank account details</td>\n</tr>\n<tr>\n<td><code>metadata</code></td>\n<td>Your custom data from initialization</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"fee-calculation\">Fee Calculation</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>fee = min(fee_cap, max(fee_floor, amount * fee_percent / 100))\nnet_amount = received_amount - fee\n\n</code></pre>","urlObject":{"host":["{{webhook_receiver_url}}"],"query":[],"variable":[]}},"response":[{"id":"3615d2fb-d66c-4231-83a2-769a436d3a63","name":"Your Server — Acknowledge","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Appia-Signature","value":"a1b2c3d4e5f6...your_hmac_sha512_signature...abcdef1234567890","description":"HMAC-SHA512 hex digest of the request body using your webhook secret"},{"key":"X-Appia-Event","value":"collection.successful"},{"key":"X-Appia-Delivery-Id","value":"12345"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"collection.successful\",\n  \"data\": {\n    \"reference\": \"ORDER-2026-001\",\n    \"internal_reference\": \"APM_x7Kf9Gh2mNpQ3R\",\n    \"status\": \"completed\",\n    \"expected_amount\": 50000,\n    \"received_amount\": 50000,\n    \"fee_amount\": 750,\n    \"net_amount\": 49250,\n    \"paid_at\": \"2026-02-28T15:05:00.000Z\",\n    \"source\": {\n      \"account_number\": \"0123456789\",\n      \"account_name\": \"JOHN DOE\",\n      \"bank_name\": \"GTBank\"\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12345\",\n      \"product\": \"Premium Plan\"\n    }\n  }\n}"},"url":"{{webhook_receiver_url}}","description":"## collection.successful\n\nSent when a customer's bank transfer is received and the full expected amount (or more) is settled to your merchant wallet.\n\n### When This Fires\n\n- Customer transfers the exact amount or more to the Providus dynamic account\n    \n- Funds are credited to your merchant wallet (minus fees)\n    \n- Fee is deducted and credited to the platform fee wallet\n    \n\n### Key Fields\n\n| Field | Description |\n| --- | --- |\n| `reference` | Your merchant reference from initialization |\n| `internal_reference` | Appia's internal reference |\n| `expected_amount` | Amount you requested |\n| `received_amount` | Amount actually received from the bank |\n| `fee_amount` | Platform fee deducted |\n| `net_amount` | Amount credited to your wallet |\n| `source` | Sender's bank account details |\n| `metadata` | Your custom data from initialization |\n\n### Fee Calculation\n\n```\nfee = min(fee_cap, max(fee_floor, amount * fee_percent / 100))\nnet_amount = received_amount - fee\n\n ```"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"received\": true\n}"}],"_postman_id":"01f7cabb-7df8-4fcf-afe6-e74dba7d2c84"},{"name":"collection.underpayment","id":"259e9d65-5c31-48e1-b816-6545c3d347be","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"noauth","isInherited":false},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Appia-Signature","value":"a1b2c3d4e5f6...your_hmac_sha512_signature...abcdef1234567890","description":"<p>HMAC-SHA512 hex digest of the request body using your webhook secret</p>\n"},{"key":"X-Appia-Event","value":"collection.underpayment"},{"key":"X-Appia-Delivery-Id","value":"12346"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"collection.underpayment\",\n  \"data\": {\n    \"reference\": \"ORDER-2026-002\",\n    \"internal_reference\": \"APM_mN3pQ7rS9tU1wX\",\n    \"status\": \"amount_mismatch\",\n    \"expected_amount\": 50000,\n    \"received_amount\": 30000,\n    \"source\": {\n      \"account_number\": \"0123456789\",\n      \"account_name\": \"JANE DOE\",\n      \"bank_name\": \"Access Bank\"\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12346\"\n    }\n  }\n}"},"url":"{{webhook_receiver_url}}","description":"<h2 id=\"collectionunderpayment\">collection.underpayment</h2>\n<p>Sent when a payment is received but the amount is less than the expected amount.</p>\n<h3 id=\"when-this-fires\">When This Fires</h3>\n<ul>\n<li>Customer transfers less than the expected amount to the dynamic account</li>\n<li>Appia automatically initiates a return of funds to the sender's account</li>\n<li>The transaction status is set to <code>amount_mismatch</code></li>\n<li>No fees are charged for underpayments</li>\n</ul>\n<h3 id=\"key-fields\">Key Fields</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>expected_amount</code></td>\n<td>Amount you requested</td>\n</tr>\n<tr>\n<td><code>received_amount</code></td>\n<td>Amount actually received (less than expected)</td>\n</tr>\n<tr>\n<td><code>source</code></td>\n<td>Sender's bank account details</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"what-happens-next\">What Happens Next</h3>\n<ul>\n<li>Funds are returned to the sender via Providus</li>\n<li>The transaction remains in <code>amount_mismatch</code> status</li>\n<li>You should prompt the customer to re-initiate the payment with the correct amount</li>\n</ul>\n","urlObject":{"host":["{{webhook_receiver_url}}"],"query":[],"variable":[]}},"response":[{"id":"96509de2-7b15-4b9b-8bee-d6dbb01bbf50","name":"Your Server — Acknowledge","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"X-Appia-Signature","value":"a1b2c3d4e5f6...your_hmac_sha512_signature...abcdef1234567890","description":"HMAC-SHA512 hex digest of the request body using your webhook secret"},{"key":"X-Appia-Event","value":"collection.underpayment"},{"key":"X-Appia-Delivery-Id","value":"12346"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"collection.underpayment\",\n  \"data\": {\n    \"reference\": \"ORDER-2026-002\",\n    \"internal_reference\": \"APM_mN3pQ7rS9tU1wX\",\n    \"status\": \"amount_mismatch\",\n    \"expected_amount\": 50000,\n    \"received_amount\": 30000,\n    \"source\": {\n      \"account_number\": \"0123456789\",\n      \"account_name\": \"JANE DOE\",\n      \"bank_name\": \"Access Bank\"\n    },\n    \"metadata\": {\n      \"order_id\": \"ORD-12346\"\n    }\n  }\n}"},"url":"{{webhook_receiver_url}}","description":"## collection.underpayment\n\nSent when a payment is received but the amount is less than the expected amount.\n\n### When This Fires\n\n- Customer transfers less than the expected amount to the dynamic account\n- Appia automatically initiates a return of funds to the sender's account\n- The transaction status is set to `amount_mismatch`\n- No fees are charged for underpayments\n\n### Key Fields\n\n| Field | Description |\n|-------|-------------|\n| `expected_amount` | Amount you requested |\n| `received_amount` | Amount actually received (less than expected) |\n| `source` | Sender's bank account details |\n\n### What Happens Next\n\n- Funds are returned to the sender via Providus\n- The transaction remains in `amount_mismatch` status\n- You should prompt the customer to re-initiate the payment with the correct amount"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"received\": true\n}"}],"_postman_id":"259e9d65-5c31-48e1-b816-6545c3d347be"}],"id":"504c39e5-9674-4cf6-a610-2c0bad42c612","description":"<p>Webhook payload examples that Appia sends to your configured webhook URL when events occur.</p>\n<p>These are <strong>POST requests you can send to your own webhook endpoint</strong> to test your handler.</p>\n<h3 id=\"webhook-headers\">Webhook Headers</h3>\n<p>Every webhook includes these headers:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Header</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>Content-Type</code></td>\n<td><code>application/json</code></td>\n</tr>\n<tr>\n<td><code>X-Appia-Signature</code></td>\n<td>HMAC-SHA512 hex digest of the JSON body using your webhook secret</td>\n</tr>\n<tr>\n<td><code>X-Appia-Event</code></td>\n<td>Event type (e.g., <code>collection.successful</code>)</td>\n</tr>\n<tr>\n<td><code>X-Appia-Delivery-Id</code></td>\n<td>Unique delivery identifier</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"retry-policy\">Retry Policy</h3>\n<ul>\n<li>Webhooks are delivered every minute for pending deliveries</li>\n<li>A <code>2xx</code> response is considered successful</li>\n<li>Failed deliveries are retried up to 5 times with backoff</li>\n<li>After 5 failed attempts, the webhook is marked as <code>exhausted</code></li>\n</ul>\n<h3 id=\"implemented-events\">Implemented Events</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Event</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>collection.successful</code></td>\n<td>Full payment received and settled to merchant wallet</td>\n</tr>\n<tr>\n<td><code>collection.underpayment</code></td>\n<td>Payment received but amount is less than expected</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"coming-soon\">Coming Soon</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Event</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>payout.completed</code></td>\n<td>Daily payout batch completed successfully</td>\n</tr>\n<tr>\n<td><code>payout.failed</code></td>\n<td>Payout transfer failed after all retries</td>\n</tr>\n</tbody>\n</table>\n</div>","_postman_id":"504c39e5-9674-4cf6-a610-2c0bad42c612","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}},{"name":"Webhook Verification","item":[{"name":"Signature Verification Guide","id":"a60c7c9f-9634-4ba4-a1c2-2caa7522b1cf","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"noauth","isInherited":false},"method":"GET","header":[],"url":"{{base_url}}","description":"<h2 id=\"webhook-signature-verification\">Webhook Signature Verification</h2>\n<p>Every webhook request includes an <code>X-Appia-Signature</code> header containing an HMAC-SHA512 hex digest. You should verify this signature to ensure the webhook is genuinely from Appia.</p>\n<h3 id=\"algorithm\">Algorithm</h3>\n<ol>\n<li>Get the raw JSON request body (do not parse and re-stringify)</li>\n<li>Compute HMAC-SHA512 using your <code>webhook_secret</code> as the key</li>\n<li>Compare the computed hex digest with the <code>X-Appia-Signature</code> header</li>\n</ol>\n<h3 id=\"nodejs-example\">Node.js Example</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">const crypto = require('crypto');\n\nfunction verifyWebhookSignature(rawBody, signature, webhookSecret) {\n  const computed = crypto\n    .createHmac('sha512', webhookSecret)\n    .update(rawBody) // Use the raw request body string\n    .digest('hex');\n  \n  return computed === signature;\n}\n\n// Express.js middleware example\napp.post('/webhooks/appia', express.raw({ type: 'application/json' }), (req, res) =&gt; {\n  const signature = req.headers['x-appia-signature'];\n  const event = req.headers['x-appia-event'];\n  const deliveryId = req.headers['x-appia-delivery-id'];\n  \n  // Verify signature\n  const isValid = verifyWebhookSignature(\n    req.body.toString(), // raw body as string\n    signature,\n    process.env.APPIA_WEBHOOK_SECRET // your whsec_... secret\n  );\n  \n  if (!isValid) {\n    console.error('Invalid webhook signature');\n    return res.status(401).json({ error: 'Invalid signature' });\n  }\n  \n  // Parse the verified body\n  const payload = JSON.parse(req.body);\n  \n  // Handle the event\n  switch (payload.event) {\n    case 'collection.successful':\n      // Payment received — fulfill the order\n      console.log('Payment received:', payload.data.reference);\n      break;\n    case 'collection.underpayment':\n      // Underpayment — notify customer\n      console.log('Underpayment:', payload.data.reference);\n      break;\n    default:\n      console.log('Unknown event:', payload.event);\n  }\n  \n  // Always respond with 2xx to acknowledge receipt\n  res.status(200).json({ received: true });\n});\n</code></pre>\n<h3 id=\"python-example\">Python Example</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-python\">import hmac\nimport hashlib\n\ndef verify_webhook(raw_body: bytes, signature: str, webhook_secret: str) -&gt; bool:\n    computed = hmac.new(\n        webhook_secret.encode('utf-8'),\n        raw_body,\n        hashlib.sha512\n    ).hexdigest()\n    return hmac.compare_digest(computed, signature)\n</code></pre>\n<h3 id=\"important-notes\">Important Notes</h3>\n<ul>\n<li>Use the <strong>raw request body</strong> for verification, not a parsed/re-serialized version</li>\n<li>The webhook secret format is <code>whsec_</code> followed by 64 hex characters</li>\n<li>Always respond with HTTP <code>2xx</code> within 10 seconds to avoid retries</li>\n<li>Use constant-time comparison (<code>===</code> in JS, <code>hmac.compare_digest</code> in Python) to prevent timing attacks</li>\n</ul>\n","urlObject":{"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"a60c7c9f-9634-4ba4-a1c2-2caa7522b1cf"}],"id":"95aa4aa8-3b1e-4538-8d72-d13b6f3dc30d","description":"<p>Guide and code snippets for verifying webhook signatures to ensure authenticity.</p>\n","_postman_id":"95aa4aa8-3b1e-4538-8d72-d13b6f3dc30d","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}},{"name":"Testing Utilities","item":[{"name":"Simulate Providus Settlement (Staging Only)","id":"257996d1-2621-4cab-b046-c6793ccb3ecb","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"noauth","isInherited":false},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"x-auth-signature","value":"{{providus_auth_signature}}","description":"<p>Providus authentication signature (from your .env PROVIDUS_AUTH_SIGNATURE)</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"sessionId\": \"TEST_SESSION_001\",\n  \"settlementId\": \"TEST_SETTLEMENT_001\",\n  \"sourceAccountNumber\": \"0123456789\",\n  \"sourceAccountName\": \"JOHN DOE TEST\",\n  \"sourceBankName\": \"GTBank\",\n  \"initiationTranRef\": \"REPLACE_WITH_INITIATION_TRAN_REF\",\n  \"accountNumber\": \"REPLACE_WITH_DYNAMIC_ACCOUNT_NUMBER\",\n  \"tranRemarks\": \"Test payment for ORDER-2026-001\",\n  \"transactionAmount\": \"50000.00\",\n  \"settledAmount\": \"50000.00\",\n  \"feeAmount\": \"0.00\",\n  \"vatAmount\": \"0.00\",\n  \"currency\": \"NGN\",\n  \"channelId\": \"1\",\n  \"tranDateTime\": \"2026-02-28 15:05:00\"\n}"},"url":"{{base_url}}/payment/providus/settlement_notif","description":"<h2 id=\"simulated-providus-settlement-webhook\">Simulated Providus Settlement Webhook</h2>\n<p><strong>WARNING: Use this in staging environments only.</strong> This simulates the webhook that Providus Bank sends when a bank transfer arrives.</p>\n<h3 id=\"setup\">Setup</h3>\n<ol>\n<li>First, call <code>POST /merchant/initialize</code> to create a transaction</li>\n<li>Copy the <code>account_number</code> from the response into the <code>accountNumber</code> field below</li>\n<li>Set <code>initiationTranRef</code> to match the Providus initiation reference (stored in DB)</li>\n<li>Set <code>transactionAmount</code> and <code>settledAmount</code> to the expected amount</li>\n<li>Set the <code>x-auth-signature</code> header to your <code>PROVIDUS_AUTH_SIGNATURE</code> env value</li>\n</ol>\n<h3 id=\"test-scenarios\">Test Scenarios</h3>\n<p><strong>Exact payment:</strong></p>\n<ul>\n<li>Set <code>transactionAmount</code> = <code>settledAmount</code> = the initialized amount</li>\n<li>Result: <code>collection.successful</code> webhook fired</li>\n</ul>\n<p><strong>Underpayment:</strong></p>\n<ul>\n<li>Set <code>transactionAmount</code> &lt; the initialized amount</li>\n<li>Result: <code>collection.underpayment</code> webhook fired, funds returned to sender</li>\n</ul>\n<h3 id=\"fields-to-replace\">Fields to Replace</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Replace With</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>initiationTranRef</code></td>\n<td>The <code>initiation_tran_ref</code> from the DB (or Providus response)</td>\n</tr>\n<tr>\n<td><code>accountNumber</code></td>\n<td>The dynamic account number from initialization response</td>\n</tr>\n<tr>\n<td><code>transactionAmount</code></td>\n<td>Amount being \"paid\" (as string with decimals)</td>\n</tr>\n<tr>\n<td><code>settledAmount</code></td>\n<td>Same as transactionAmount for testing</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["payment","providus","settlement_notif"],"host":["{{base_url}}"],"query":[],"variable":[]}},"response":[{"id":"66eff852-5ee7-4fa2-8b1c-a43e7a0abf5e","name":"Success — Settlement Processed","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"x-auth-signature","value":"{{providus_auth_signature}}","description":"Providus authentication signature (from your .env PROVIDUS_AUTH_SIGNATURE)"}],"body":{"mode":"raw","raw":"{\n  \"sessionId\": \"TEST_SESSION_001\",\n  \"settlementId\": \"TEST_SETTLEMENT_001\",\n  \"sourceAccountNumber\": \"0123456789\",\n  \"sourceAccountName\": \"JOHN DOE TEST\",\n  \"sourceBankName\": \"GTBank\",\n  \"initiationTranRef\": \"REPLACE_WITH_INITIATION_TRAN_REF\",\n  \"accountNumber\": \"REPLACE_WITH_DYNAMIC_ACCOUNT_NUMBER\",\n  \"tranRemarks\": \"Test payment for ORDER-2026-001\",\n  \"transactionAmount\": \"50000.00\",\n  \"settledAmount\": \"50000.00\",\n  \"feeAmount\": \"0.00\",\n  \"vatAmount\": \"0.00\",\n  \"currency\": \"NGN\",\n  \"channelId\": \"1\",\n  \"tranDateTime\": \"2026-02-28 15:05:00\"\n}"},"url":"{{base_url}}/payment/providus/settlement_notif","description":"## Simulated Providus Settlement Webhook\n\n**WARNING: Use this in staging environments only.** This simulates the webhook that Providus Bank sends when a bank transfer arrives.\n\n### Setup\n\n1. First, call `POST /merchant/initialize` to create a transaction\n2. Copy the `account_number` from the response into the `accountNumber` field below\n3. Set `initiationTranRef` to match the Providus initiation reference (stored in DB)\n4. Set `transactionAmount` and `settledAmount` to the expected amount\n5. Set the `x-auth-signature` header to your `PROVIDUS_AUTH_SIGNATURE` env value\n\n### Test Scenarios\n\n**Exact payment:**\n- Set `transactionAmount` = `settledAmount` = the initialized amount\n- Result: `collection.successful` webhook fired\n\n**Underpayment:**\n- Set `transactionAmount` < the initialized amount\n- Result: `collection.underpayment` webhook fired, funds returned to sender\n\n### Fields to Replace\n\n| Field | Replace With |\n|-------|-------------|\n| `initiationTranRef` | The `initiation_tran_ref` from the DB (or Providus response) |\n| `accountNumber` | The dynamic account number from initialization response |\n| `transactionAmount` | Amount being \"paid\" (as string with decimals) |\n| `settledAmount` | Same as transactionAmount for testing |"},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"requestSuccessful\": true,\n  \"sessionId\": \"TEST_SESSION_001\",\n  \"responseMessage\": \"Success\",\n  \"responseCode\": \"00\"\n}"}],"_postman_id":"257996d1-2621-4cab-b046-c6793ccb3ecb"}],"id":"b23a59e0-68ea-48e5-b17a-f498fdd4b380","description":"<p>Test payloads for simulating webhook events in staging environments.</p>\n","_postman_id":"b23a59e0-68ea-48e5-b17a-f498fdd4b380","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]},"isInherited":true,"source":{"_postman_id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","id":"d4b44c70-0e5b-4048-bc2d-038b73404b37","name":"Appia Merchant Collection API","type":"collection"}}}],"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":"{{merchant_api_key}}"}]}},"event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["// Collection-level pre-request script","// Sets Authorization header from environment variable for all requests","// (except webhook reference requests which target localhost)",""],"id":"90a508d3-d4cd-4d5f-83a6-bfee2dded594"}}]}