{"info":{"_postman_id":"9ff096d2-310e-48f9-88ce-16bd5c20c621","name":"OmniPay API Reference","description":"<html><head></head><body><p>OmniPay provides customer verification, wallet access, and payment collection through dynamic virtual accounts.</p>\n<p>KYC is the entry point. After a retailer completes verification, the <code>kyconboarding.completed</code> webhook returns:</p>\n<ul>\n<li><code>customerRef</code>, used to create a Wallet SDK session</li>\n<li><code>walletId</code>, used to direct an order payment to the retailer's wallet</li>\n</ul>\n<h2 id=\"kyc-onboarding\">KYC onboarding</h2>\n<p>OmniPay KYC is available for web and React Native.</p>\n<h3 id=\"create-a-kyc-session\">Create a KYC session</h3>\n<p>Call <strong>Create or resume KYC session</strong> when the retailer starts verification. If the response status is <code>active</code>, render <code>Kyc.Onboarding</code> with the returned <code>token</code>. Reuse the same customer details to resume an unfinished session.</p>\n<p>The SDK can request a replacement token after the initial token expires. The <code>getToken</code> callback must create or resume the same session and resolve with the new <code>token</code>.</p>\n<h3 id=\"react-web\">React web</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">npm install @omniretail/kyc-react-sdk\n</code></pre>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-tsx\">import {Kyc} from '@omniretail/kyc-react-sdk';\nimport '@omniretail/kyc-react-sdk/styles.css';\n\n&lt;Kyc.Onboarding\n  env=\"dev\"\n  token={kycToken}\n  getToken={refreshKycToken}\n  primaryColor=\"#A682FF\"\n  onComplete={refreshCustomerStatus}\n  onClose={() =&gt; history.back()}\n  onTokenExpired={restartVerification}\n  onError={error =&gt; reportErrorCode(error.code)}\n/&gt;\n</code></pre>\n<h3 id=\"react-native\">React Native</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">npm install @omniretail/kyc-sdk \\\n  react-native-webview react-native-safe-area-context \\\n  react-native-image-picker react-native-geolocation-service react-native-device-info \\\n  @react-native-async-storage/async-storage @react-native-documents/picker \\\n  @react-native-community/datetimepicker\n</code></pre>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-tsx\">import {Kyc} from '@omniretail/kyc-sdk';\n\n&lt;Kyc.Onboarding\n  env=\"dev\"\n  token={kycToken}\n  getToken={refreshKycToken}\n  primaryColor=\"#A682FF\"\n  onComplete={refreshCustomerStatus}\n  onClose={closeVerification}\n  onTokenExpired={restartVerification}\n  onError={error =&gt; reportErrorCode(error.code)}\n/&gt;\n</code></pre>\n<h3 id=\"session-props\">Session props</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Prop</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>env</code></td>\n<td>yes</td>\n<td><code>dev</code> or <code>prod</code>. Must match the KYC session environment.</td>\n</tr>\n<tr>\n<td><code>token</code></td>\n<td>yes</td>\n<td>Restricted token returned for an active KYC session.</td>\n</tr>\n<tr>\n<td><code>getToken</code></td>\n<td>no</td>\n<td>Async callback that resolves with a fresh token for the same session.</td>\n</tr>\n<tr>\n<td><code>primaryColor</code></td>\n<td>no</td>\n<td>Three- or six-digit hex colour. Defaults to <code>#A682FF</code>.</td>\n</tr>\n<tr>\n<td><code>onComplete</code></td>\n<td>yes</td>\n<td>Called when the retailer reaches the end of the KYC journey.</td>\n</tr>\n<tr>\n<td><code>onClose</code></td>\n<td>yes</td>\n<td>Called when the retailer closes KYC.</td>\n</tr>\n<tr>\n<td><code>onTokenExpired</code></td>\n<td>no</td>\n<td>Called when the SDK cannot refresh an expired token.</td>\n</tr>\n<tr>\n<td><code>onError</code></td>\n<td>no</td>\n<td>Receives the SDK error code and message.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Treat the <code>kyconboarding.completed</code> webhook as the final confirmation of verification.</p>\n<p>React Native applications must declare camera, photo-library, foreground-location, and internet permissions. Run CocoaPods on iOS and rebuild the application after installing the native dependencies.</p>\n<h2 id=\"wallet-sdk\">Wallet SDK</h2>\n<p>Display a retailer's OmniPay wallet in a React Native application. The <code>Wallet</code> component opens in a native modal.</p>\n<h3 id=\"create-a-session\">Create a session</h3>\n<p>Create a Wallet SDK session with the <code>customerRef</code> received in the KYC completion webhook. The response contains <code>data.sessionId</code>, which is passed to the component. Create a new session when it expires.</p>\n<h3 id=\"install\">Install</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">npm install @omniretail/wallet-sdk \\\n  react-native-webview react-native-device-info \\\n  react-native-select-contact react-native-share\n</code></pre>\n<p>Run CocoaPods on iOS, then rebuild the application.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-bash\">npx pod-install\n</code></pre>\n<h3 id=\"render-the-wallet\">Render the wallet</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-tsx\">import {useState} from 'react';\nimport {Button} from 'react-native';\nimport {Wallet} from '@omniretail/wallet-sdk';\n\nconst OMNIPAY_PUBLIC_KEY =\n  'OMNIPUBKEY_FLX4HPQKKX124QBVQIKAAKSUNX4FIIXC';\n\nexport function WalletScreen({customerRef, sessionId}) {\n  const [walletOpen, setWalletOpen] = useState(false);\n\n  return (\n    &lt;&gt;\n      &lt;Button title=\"Open wallet\" onPress={() =&gt; setWalletOpen(true)} /&gt;\n\n      {walletOpen ? (\n        &lt;Wallet\n          env=\"dev\"\n          publicKey={OMNIPAY_PUBLIC_KEY}\n          customerRef={customerRef}\n          sessionId={sessionId}\n          features={{\n            airtimeAndData: true,\n            bills: true,\n            paylater: true,\n            transfers: true,\n          }}\n          onClose={() =&gt; setWalletOpen(false)}\n        /&gt;\n      ) : null}\n    &lt;/&gt;\n  );\n}\n</code></pre>\n<h3 id=\"props\">Props</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Prop</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>env</code></td>\n<td>yes</td>\n<td><code>dev</code> or <code>prod</code>. Must match the session environment.</td>\n</tr>\n<tr>\n<td><code>publicKey</code></td>\n<td>yes</td>\n<td>Public key for the selected environment.</td>\n</tr>\n<tr>\n<td><code>customerRef</code></td>\n<td>yes</td>\n<td>Value from <code>data.customerRef</code> in the KYC completion webhook.</td>\n</tr>\n<tr>\n<td><code>sessionId</code></td>\n<td>yes</td>\n<td>Value from <code>data.sessionId</code> in the Wallet SDK session response.</td>\n</tr>\n<tr>\n<td><code>onClose</code></td>\n<td>yes</td>\n<td>Called after the wallet modal closes.</td>\n</tr>\n<tr>\n<td><code>primaryColor</code></td>\n<td>no</td>\n<td>Three- or six-digit hex colour. Defaults to <code>#A682FF</code>.</td>\n</tr>\n<tr>\n<td><code>features</code></td>\n<td>no</td>\n<td>Controls access to airtime and data, bills, Paylater, and transfers.</td>\n</tr>\n<tr>\n<td><code>onError</code></td>\n<td>no</td>\n<td>Receives the SDK error code and message.</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"collect-payment-with-a-dynamic-virtual-account\">Collect payment with a dynamic virtual account</h2>\n<p>Collect a bank transfer for an order with a single-use dynamic virtual account. The order identifies the retailer's wallet, and the account details are presented to the customer making the payment.</p>\n<h3 id=\"create-a-payment\">Create a payment</h3>\n<ol>\n<li>Create an order for the payment amount and set <code>metadata.receiverWalletId</code> to the retailer's <code>walletId</code>.</li>\n<li>Create a dynamic virtual account with the same <code>orderId</code> and amount.</li>\n<li>Show the returned bank name, account number, account name, amount, and expiry time.</li>\n<li>Confirm payment only after receiving <code>orderpayment.successful</code>.</li>\n</ol>\n<p>Amounts are sent in kobo. Both requests require <code>apiKey</code> and <code>IdempotencyKey</code> headers. Use a new idempotency key for each operation and retain it when retrying that operation.</p>\n<h2 id=\"environments\">Environments</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Environment</th>\n<th>API base URL</th>\n<th>SDK <code>env</code></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Development</td>\n<td><code>https://api-dev.ompy.ng</code></td>\n<td><code>dev</code></td>\n</tr>\n<tr>\n<td>Production</td>\n<td><code>https://api.ompy.ng</code></td>\n<td><code>prod</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>Credentials and SDK sessions are specific to an environment.</p>\n<h2 id=\"test-credentials\">Test credentials</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Credential</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>API key</td>\n<td><code>xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6</code></td>\n</tr>\n<tr>\n<td>Wallet SDK public key</td>\n<td><code>OMNIPUBKEY_FLX4HPQKKX124QBVQIKAAKSUNX4FIIXC</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>These credentials are valid in the development environment. Production credentials are issued during go-live.</p>\n<h2 id=\"authentication\">Authentication</h2>\n<p>Authenticate API requests with the <code>apiKey</code> header. API keys are secret and must never be included in web or mobile applications.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-http\">apiKey: xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6\n</code></pre>\n<h2 id=\"amounts\">Amounts</h2>\n<p>Amounts are integer values in kobo. For example, NGN 37,000.00 is <code>3700000</code>.</p>\n<h2 id=\"idempotent-requests\">Idempotent requests</h2>\n<p>Order and dynamic-account requests require an <code>IdempotencyKey</code> header. Generate a value between 8 and 50 characters for a new request, and retain it for retries of that request. A different operation requires a new value.</p>\n<h2 id=\"webhooks\">Webhooks</h2>\n<p>Register an HTTPS webhook URL with OmniPay before going live.</p>\n<p>Each webhook includes a <code>signature</code> header containing the hexadecimal HMAC-SHA512 signature of the raw request body. Compute the signature with the OmniPay API key and compare it before parsing the JSON.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-js\">import crypto from 'node:crypto';\n\nfunction verifyOmniPaySignature(rawBody, signature, apiKey) {\n  if (!signature || !/^[0-9a-f]+$/i.test(signature)) return false;\n\n  const expected = crypto\n    .createHmac('sha512', apiKey)\n    .update(rawBody)\n    .digest();\n  const received = Buffer.from(signature, 'hex');\n\n  return received.length === expected.length &amp;&amp;\n    crypto.timingSafeEqual(received, expected);\n}\n\napp.post(\n  '/webhooks/omnipay',\n  express.raw({type: 'application/json'}),\n  async (req, res) =&gt; {\n    if (!verifyOmniPaySignature(\n      req.body,\n      req.get('signature'),\n      process.env.OMNIPAY_API_KEY,\n    )) {\n      return res.sendStatus(401);\n    }\n\n    const event = JSON.parse(req.body.toString('utf8'));\n    await processOmniPayEvent(event);\n    return res.sendStatus(200);\n  },\n);\n</code></pre>\n<p>A webhook can be delivered more than once. Store the event before returning HTTP <code>200</code>, and make processing idempotent using <code>referenceId</code> or <code>transactionId</code>.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"56708741","collectionId":"9ff096d2-310e-48f9-88ce-16bd5c20c621","publishedId":"2sBY4Tpctg","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-07-31T18:56:55.000Z"},"item":[{"name":"KYC onboarding","item":[{"name":"Create or resume KYC session","event":[{"listen":"test","script":{"type":"text/javascript","exec":["const body = pm.response.json();","if (body.token) pm.collectionVariables.set('kycToken', body.token);","pm.test('Session is active or completed', () => pm.expect(['active', 'completed']).to.include(body.status));","if (body.status === 'active') pm.test('Restricted token returned', () => pm.expect(body.token).to.be.a('string').and.not.empty);"]}}],"id":"a3ce8f14-5d83-41f9-9bf0-f8d9a6041dcf","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"<p>Development API key. Keep it out of client code.</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"referenceId\": \"customer_1001\",\n  \"phoneNumber\": \"08012345678\",\n  \"profileType\": \"secondary\",\n  \"emailAddress\": \"customer@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/kycservice/session","description":"<p>Creates a KYC session or returns the state of an existing session.</p>\n<p>Supply the same <code>referenceId</code>, <code>phoneNumber</code>, and <code>emailAddress</code> to resume an unfinished session.</p>\n<h2 id=\"parameters\">Parameters</h2>\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>referenceId</code></td>\n<td>string</td>\n<td>yes</td>\n<td>Unique, stable customer identifier.</td>\n</tr>\n<tr>\n<td><code>phoneNumber</code></td>\n<td>string</td>\n<td>yes</td>\n<td>Retailer's phone number.</td>\n</tr>\n<tr>\n<td><code>profileType</code></td>\n<td>string</td>\n<td>yes</td>\n<td><code>secondary</code> for a retailer.</td>\n</tr>\n<tr>\n<td><code>emailAddress</code></td>\n<td>string</td>\n<td>yes</td>\n<td>Retailer's email address.</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"returns\">Returns</h2>\n<p>An active session returns <code>status</code>, <code>token</code>, and <code>expiresAt</code>. Pass <code>token</code> to <code>Kyc.Onboarding</code>.</p>\n<p>A completed session returns <code>status</code> and <code>identityNumber</code>. Wait for the completion webhook to obtain <code>customerRef</code> and <code>walletId</code>.</p>\n","urlObject":{"path":["kycservice","session"],"host":["https://api-dev.ompy.ng"],"query":[],"variable":[]}},"response":[{"id":"a376e90c-81b1-446e-8c0e-aa7d962b6fc5","name":"200 - Active session","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"Development API key. Keep it out of client code."}],"body":{"mode":"raw","raw":"{\n  \"referenceId\": \"customer_1001\",\n  \"phoneNumber\": \"08012345678\",\n  \"profileType\": \"secondary\",\n  \"emailAddress\": \"customer@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/kycservice/session","description":"Creates a KYC session or returns the state of an existing session.\n\nSupply the same `referenceId`, `phoneNumber`, and `emailAddress` to resume an unfinished session.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `referenceId` | string | yes | Unique, stable customer identifier. |\n| `phoneNumber` | string | yes | Retailer's phone number. |\n| `profileType` | string | yes | `secondary` for a retailer. |\n| `emailAddress` | string | yes | Retailer's email address. |\n\n## Returns\n\nAn active session returns `status`, `token`, and `expiresAt`. Pass `token` to `Kyc.Onboarding`.\n\nA completed session returns `status` and `identityNumber`. Wait for the completion webhook to obtain `customerRef` and `walletId`."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"active\",\n  \"token\": \"restricted-kyc-token\",\n  \"expiresAt\": \"2026-07-31T18:30:00Z\",\n  \"profileType\": \"secondary\"\n}"},{"id":"cf4d208b-7e65-4c8e-93a4-e757d6cd24da","name":"200 - KYC already completed","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"Development API key. Keep it out of client code."}],"body":{"mode":"raw","raw":"{\n  \"referenceId\": \"customer_1001\",\n  \"phoneNumber\": \"08012345678\",\n  \"profileType\": \"secondary\",\n  \"emailAddress\": \"customer@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/kycservice/session","description":"Creates a KYC session or returns the state of an existing session.\n\nSupply the same `referenceId`, `phoneNumber`, and `emailAddress` to resume an unfinished session.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `referenceId` | string | yes | Unique, stable customer identifier. |\n| `phoneNumber` | string | yes | Retailer's phone number. |\n| `profileType` | string | yes | `secondary` for a retailer. |\n| `emailAddress` | string | yes | Retailer's email address. |\n\n## Returns\n\nAn active session returns `status`, `token`, and `expiresAt`. Pass `token` to `Kyc.Onboarding`.\n\nA completed session returns `status` and `identityNumber`. Wait for the completion webhook to obtain `customerRef` and `walletId`."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"completed\",\n  \"identityNumber\": \"291fc12b5046c93dadc45d5eaa157624aa071b429a0d27ed8df6ce0b6cb9699e\",\n  \"profileType\": \"secondary\"\n}"},{"id":"75feb89d-6c13-444f-a3cb-ce3850588161","name":"409 - Reference conflicts with existing details","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"Development API key. Keep it out of client code."}],"body":{"mode":"raw","raw":"{\n  \"referenceId\": \"customer_1001\",\n  \"phoneNumber\": \"08012345678\",\n  \"profileType\": \"secondary\",\n  \"emailAddress\": \"customer@example.com\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/kycservice/session","description":"Creates a KYC session or returns the state of an existing session.\n\nSupply the same `referenceId`, `phoneNumber`, and `emailAddress` to resume an unfinished session.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `referenceId` | string | yes | Unique, stable customer identifier. |\n| `phoneNumber` | string | yes | Retailer's phone number. |\n| `profileType` | string | yes | `secondary` for a retailer. |\n| `emailAddress` | string | yes | Retailer's email address. |\n\n## Returns\n\nAn active session returns `status`, `token`, and `expiresAt`. Pass `token` to `Kyc.Onboarding`.\n\nA completed session returns `status` and `identityNumber`. Wait for the completion webhook to obtain `customerRef` and `walletId`."},"status":"Conflict","code":409,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"code\": \"session_conflict\",\n  \"message\": \"This verification session was started for different account details.\"\n}"}],"_postman_id":"a3ce8f14-5d83-41f9-9bf0-f8d9a6041dcf"},{"name":"[WEBHOOK] KYC completed and wallet created","id":"8c9c0562-d467-4c0e-84d7-8a737da098dd","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"signature","value":"<webhook-signature>","description":"<p>HMAC-SHA512 signature of the webhook payload, created with the OmniPay API key.</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"kyconboarding.completed\",\n  \"data\": {\n    \"referenceId\": \"customer_1001\",\n    \"identityNumber\": \"291fc12b5046c93dadc45d5eaa157624aa071b429a0d27ed8df6ce0b6cb9699e\",\n    \"createdAt\": \"2026-07-31T17:30:00Z\",\n    \"customerRef\": \"customer-ref-from-omnipay\",\n    \"walletId\": \"wallet-id-from-omnipay\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"https://example.com/webhooks/omnipay","description":"<p>Occurs after KYC is completed and the retailer's wallet is ready. Verify the webhook signature before processing the payload.</p>\n<h2 id=\"event-data\">Event data</h2>\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>data.referenceId</code></td>\n<td>Customer identifier supplied when the KYC session was created.</td>\n</tr>\n<tr>\n<td><code>data.identityNumber</code></td>\n<td>OmniPay identity identifier.</td>\n</tr>\n<tr>\n<td><code>data.createdAt</code></td>\n<td>Time the event was created.</td>\n</tr>\n<tr>\n<td><code>data.customerRef</code></td>\n<td>Customer reference used to create Wallet SDK sessions.</td>\n</tr>\n<tr>\n<td><code>data.walletId</code></td>\n<td>Wallet identifier used as the payment destination on an order.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Match the event to the customer using <code>data.referenceId</code>, store <code>customerRef</code> and <code>walletId</code>, then return HTTP <code>200</code>. Processing must be idempotent because the event can be delivered more than once.</p>\n","urlObject":{"host":["https://example.com/webhooks/omnipay"],"query":[],"variable":[]}},"response":[{"id":"a1905b7c-5681-4c27-a0ea-4a0b6221870d","name":"200 - Acknowledged","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"signature","value":"<webhook-signature>","description":"HMAC-SHA512 signature of the webhook payload, created with the OmniPay API key."}],"body":{"mode":"raw","raw":"{\n  \"event\": \"kyconboarding.completed\",\n  \"data\": {\n    \"referenceId\": \"customer_1001\",\n    \"identityNumber\": \"291fc12b5046c93dadc45d5eaa157624aa071b429a0d27ed8df6ce0b6cb9699e\",\n    \"createdAt\": \"2026-07-31T17:30:00Z\",\n    \"customerRef\": \"customer-ref-from-omnipay\",\n    \"walletId\": \"wallet-id-from-omnipay\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"https://example.com/webhooks/omnipay","description":"Occurs after KYC is completed and the retailer's wallet is ready. Verify the webhook signature before processing the payload.\n\n## Event data\n\n| Field | Description |\n|---|---|\n| `data.referenceId` | Customer identifier supplied when the KYC session was created. |\n| `data.identityNumber` | OmniPay identity identifier. |\n| `data.createdAt` | Time the event was created. |\n| `data.customerRef` | Customer reference used to create Wallet SDK sessions. |\n| `data.walletId` | Wallet identifier used as the payment destination on an order. |\n\nMatch the event to the customer using `data.referenceId`, store `customerRef` and `walletId`, then return HTTP `200`. Processing must be idempotent because the event can be delivered more than once."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"statusCode\": 200,\n  \"message\": \"Success\"\n}"}],"_postman_id":"8c9c0562-d467-4c0e-84d7-8a737da098dd"}],"id":"89f726a1-e6e0-454d-b673-b4a7002f3781","_postman_id":"89f726a1-e6e0-454d-b673-b4a7002f3781","description":""},{"name":"Wallet SDK","item":[{"name":"Create Wallet SDK session","event":[{"listen":"test","script":{"type":"text/javascript","exec":["const body = pm.response.json();","if (body.data?.sessionId) pm.collectionVariables.set('walletSessionId', body.data.sessionId);","pm.test('Wallet SDK session created', () => {","  pm.expect(pm.response.code).to.eql(200);","  pm.expect(body.error).to.eql(false);","  pm.expect(body.data.sessionId).to.be.a('string').and.not.empty;","});"]}}],"id":"74b5e7b0-636e-4de0-b853-3f44b1be19d4","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"<p>Development API key. Keep it out of client code.</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"customerRef\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/sdk/createSession","description":"<p>Creates a short-lived session for the React Native Wallet SDK.</p>\n<h2 id=\"parameters\">Parameters</h2>\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>customerRef</code></td>\n<td>string</td>\n<td>yes</td>\n<td>Value from <code>data.customerRef</code> in the KYC completion webhook.</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"returns\">Returns</h2>\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>data.sessionId</code></td>\n<td>Session identifier passed to the <code>Wallet</code> component.</td>\n</tr>\n<tr>\n<td><code>data.expiresIn</code></td>\n<td>Number of seconds before the session expires.</td>\n</tr>\n<tr>\n<td><code>data.sessionToken</code></td>\n<td>OmniPay session credential. Keep this value out of the mobile application.</td>\n</tr>\n</tbody>\n</table>\n</div><p>The <code>Wallet</code> component requires <code>data.sessionId</code> and <code>customerRef</code>.</p>\n","urlObject":{"path":["sdk","createSession"],"host":["https://api-dev.ompy.ng"],"query":[],"variable":[]}},"response":[{"id":"724133c7-6c7d-452c-9805-205ad9e4487b","name":"200 - Wallet SDK session created","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"Development API key. Keep it out of client code."}],"body":{"mode":"raw","raw":"{\n  \"customerRef\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/sdk/createSession","description":"Creates a short-lived session for the React Native Wallet SDK.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `customerRef` | string | yes | Value from `data.customerRef` in the KYC completion webhook. |\n\n## Returns\n\n| Field | Description |\n|---|---|\n| `data.sessionId` | Session identifier passed to the `Wallet` component. |\n| `data.expiresIn` | Number of seconds before the session expires. |\n| `data.sessionToken` | OmniPay session credential. Keep this value out of the mobile application. |\n\nThe `Wallet` component requires `data.sessionId` and `customerRef`."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": false,\n  \"message\": \"Session Started Successfully\",\n  \"data\": {\n    \"sessionId\": \"4354d26b1b5ac968e349ef25bad47dc63c622cc55955b18d0224f8ac804ac920\",\n    \"expiresIn\": 259200,\n    \"sessionToken\": \"wallet-sdk-session-token\"\n  }\n}"},{"id":"65ab51e0-a5b4-4c90-8803-250d0cdc903f","name":"400 - Invalid customer reference","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","description":"Development API key. Keep it out of client code."}],"body":{"mode":"raw","raw":"{\n  \"customerRef\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/sdk/createSession","description":"Creates a short-lived session for the React Native Wallet SDK.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `customerRef` | string | yes | Value from `data.customerRef` in the KYC completion webhook. |\n\n## Returns\n\n| Field | Description |\n|---|---|\n| `data.sessionId` | Session identifier passed to the `Wallet` component. |\n| `data.expiresIn` | Number of seconds before the session expires. |\n| `data.sessionToken` | OmniPay session credential. Keep this value out of the mobile application. |\n\nThe `Wallet` component requires `data.sessionId` and `customerRef`."},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": true,\n  \"message\": \"Invalid Customer Ref\",\n  \"data\": {\n    \"sessionId\": null,\n    \"expiresIn\": 0,\n    \"sessionToken\": null\n  }\n}"}],"_postman_id":"74b5e7b0-636e-4de0-b853-3f44b1be19d4"}],"id":"355daad6-f76e-43f4-b5e6-d774da2a7054","_postman_id":"355daad6-f76e-43f4-b5e6-d774da2a7054","description":""},{"name":"Collect payment with a dynamic virtual account","item":[{"name":"Create order","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["if (!pm.collectionVariables.get('orderIdempotencyKey')) {","  pm.collectionVariables.set('orderIdempotencyKey', pm.variables.replaceIn('8369d315-7f09-4a4e-9957-b76b69b1bfb1'));","}"]}},{"listen":"test","script":{"type":"text/javascript","exec":["pm.test('Order accepted', () => pm.expect(pm.response.code).to.be.oneOf([200, 201]));"]}}],"id":"63454075-1d10-4271-9c98-31b5939cd46e","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"orderId\": \"SO_1001\",\n  \"orderAmount\": 3700000,\n  \"metadata\": \"{\\\"receiverWalletId\\\":\\\"\\\"}\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Order/CreateOrder","description":"<p>Creates an order for a payment to the retailer's wallet.</p>\n<h2 id=\"parameters\">Parameters</h2>\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>orderId</code></td>\n<td>string</td>\n<td>yes</td>\n<td><code>SO_{order id on their system}</code>. For example, order <code>1001</code> is <code>SO_1001</code>. Must be unique.</td>\n</tr>\n<tr>\n<td><code>orderAmount</code></td>\n<td>integer</td>\n<td>yes</td>\n<td>Payment amount in kobo. For example, NGN 5,000.00 is <code>500000</code>.</td>\n</tr>\n<tr>\n<td><code>metadata</code></td>\n<td>string</td>\n<td>yes</td>\n<td>JSON string containing <code>receiverWalletId</code>, set to the retailer's <code>walletId</code>.</td>\n</tr>\n</tbody>\n</table>\n</div><p><code>metadata</code> is JSON encoded as a string. Escape its quotation marks as shown in the request body.</p>\n<h2 id=\"returns\">Returns</h2>\n<p>Returns HTTP <code>201</code> when the order is created. Use the same <code>orderId</code> and <code>orderAmount</code> to create the dynamic virtual account.</p>\n","urlObject":{"path":["Order","CreateOrder"],"host":["https://api-dev.ompy.ng"],"query":[],"variable":[]}},"response":[{"id":"3b678c4c-628c-4997-acd6-983aa2ab300f","name":"201 - Order created","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"orderId\": \"SO_1001\",\n  \"orderAmount\": 3700000,\n  \"metadata\": \"{\\\"receiverWalletId\\\":\\\"\\\"}\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Order/CreateOrder","description":"Creates an order for a payment to the retailer's wallet.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `orderId` | string | yes | `SO_{order id on their system}`. For example, order `1001` is `SO_1001`. Must be unique. |\n| `orderAmount` | integer | yes | Payment amount in kobo. For example, NGN 5,000.00 is `500000`. |\n| `metadata` | string | yes | JSON string containing `receiverWalletId`, set to the retailer's `walletId`. |\n\n`metadata` is JSON encoded as a string. Escape its quotation marks as shown in the request body.\n\n## Returns\n\nReturns HTTP `201` when the order is created. Use the same `orderId` and `orderAmount` to create the dynamic virtual account."},"status":"Created","code":201,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": false,\n  \"message\": \"Order created successfully\",\n  \"data\": null\n}"},{"id":"b48d654a-b306-46b3-bae9-9d632d3202ea","name":"400 - Validation error","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"orderId\": \"SO_1001\",\n  \"orderAmount\": 3700000,\n  \"metadata\": \"{\\\"receiverWalletId\\\":\\\"\\\"}\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Order/CreateOrder","description":"Creates an order for a payment to the retailer's wallet.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `orderId` | string | yes | `SO_{order id on their system}`. For example, order `1001` is `SO_1001`. Must be unique. |\n| `orderAmount` | integer | yes | Payment amount in kobo. For example, NGN 5,000.00 is `500000`. |\n| `metadata` | string | yes | JSON string containing `receiverWalletId`, set to the retailer's `walletId`. |\n\n`metadata` is JSON encoded as a string. Escape its quotation marks as shown in the request body.\n\n## Returns\n\nReturns HTTP `201` when the order is created. Use the same `orderId` and `orderAmount` to create the dynamic virtual account."},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": true,\n  \"message\": \"Order amount should be greater than 0\",\n  \"data\": null\n}"}],"_postman_id":"63454075-1d10-4271-9c98-31b5939cd46e"},{"name":"Create dynamic virtual account","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["if (!pm.collectionVariables.get('dynamicAccountIdempotencyKey')) {","  pm.collectionVariables.set('dynamicAccountIdempotencyKey', pm.variables.replaceIn('4d8debf7-ee5d-4227-9cf1-7d97a304c8ac'));","}"]}},{"listen":"test","script":{"type":"text/javascript","exec":["const body = pm.response.json();","pm.test('Dynamic account created', () => {","  pm.expect(pm.response.code).to.eql(200);","  pm.expect(body.error).to.eql(false);","  pm.expect(body.data.accountNumber).to.be.a('string').and.not.empty;","  pm.expect(body.data.bankName).to.eql('Victory Mfb');","});"]}}],"id":"390b7466-be77-42c6-98e2-0951e3bb998e","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"amount\": 3700000,\n  \"orderId\": \"SO_1001\",\n  \"accountName\": \"Ada Customer\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Wallet/CreateDynamicAccount","description":"<p>Creates a temporary bank account for an existing order.</p>\n<h2 id=\"parameters\">Parameters</h2>\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>amount</code></td>\n<td>integer</td>\n<td>yes</td>\n<td>Exact order amount in kobo.</td>\n</tr>\n<tr>\n<td><code>orderId</code></td>\n<td>string</td>\n<td>yes</td>\n<td><code>orderId</code> of the existing order.</td>\n</tr>\n<tr>\n<td><code>accountName</code></td>\n<td>string</td>\n<td>yes</td>\n<td>Account name shown to the customer. Accepts letters and spaces.</td>\n</tr>\n</tbody>\n</table>\n</div><p><code>amount</code> must equal the order's <code>orderAmount</code>.</p>\n<h2 id=\"returns\">Returns</h2>\n<p>The response contains <code>accountName</code>, <code>accountNumber</code>, <code>bankName</code>, <code>bankCode</code>, <code>referenceId</code>, and <code>expiresIn</code>. The bank is <code>Victory Mfb</code>.</p>\n<p>Display the account details with the exact payment amount and expiry time. Stop accepting payment to the account after it expires. Account creation does not confirm that the order has been paid.</p>\n","urlObject":{"path":["Wallet","CreateDynamicAccount"],"host":["https://api-dev.ompy.ng"],"query":[],"variable":[]}},"response":[{"id":"61630e18-05b6-442a-bceb-dfb7f789cbdf","name":"200 - Dynamic account ready","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"amount\": 3700000,\n  \"orderId\": \"SO_1001\",\n  \"accountName\": \"Ada Customer\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Wallet/CreateDynamicAccount","description":"Creates a temporary bank account for an existing order.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `amount` | integer | yes | Exact order amount in kobo. |\n| `orderId` | string | yes | `orderId` of the existing order. |\n| `accountName` | string | yes | Account name shown to the customer. Accepts letters and spaces. |\n\n`amount` must equal the order's `orderAmount`.\n\n## Returns\n\nThe response contains `accountName`, `accountNumber`, `bankName`, `bankCode`, `referenceId`, and `expiresIn`. The bank is `Victory Mfb`.\n\nDisplay the account details with the exact payment amount and expiry time. Stop accepting payment to the account after it expires. Account creation does not confirm that the order has been paid."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": false,\n  \"message\": \"Dynamic account created successfully\",\n  \"data\": {\n    \"accountNumber\": \"0123456789\",\n    \"bankCode\": \"090813\",\n    \"bankName\": \"Victory Mfb\",\n    \"referenceId\": \"orderIdSO_1001\",\n    \"accountName\": \"Ada Customer\",\n    \"expiresIn\": 3590.0\n  }\n}"},{"id":"a7dfbc6a-33e3-4977-b96d-2cfbfe54c504","name":"400 - Order missing or already paid","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6"},{"key":"IdempotencyKey","value":""}],"body":{"mode":"raw","raw":"{\n  \"amount\": 3700000,\n  \"orderId\": \"SO_1001\",\n  \"accountName\": \"Ada Customer\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api-dev.ompy.ng/Wallet/CreateDynamicAccount","description":"Creates a temporary bank account for an existing order.\n\n## Parameters\n\n| Field | Type | Required | Description |\n|---|---|---:|---|\n| `amount` | integer | yes | Exact order amount in kobo. |\n| `orderId` | string | yes | `orderId` of the existing order. |\n| `accountName` | string | yes | Account name shown to the customer. Accepts letters and spaces. |\n\n`amount` must equal the order's `orderAmount`.\n\n## Returns\n\nThe response contains `accountName`, `accountNumber`, `bankName`, `bankCode`, `referenceId`, and `expiresIn`. The bank is `Victory Mfb`.\n\nDisplay the account details with the exact payment amount and expiry time. Stop accepting payment to the account after it expires. Account creation does not confirm that the order has been paid."},"status":"Bad Request","code":400,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"error\": true,\n  \"message\": \"Order already paid for\",\n  \"data\": null\n}"}],"_postman_id":"390b7466-be77-42c6-98e2-0951e3bb998e"},{"name":"[WEBHOOK] Order payment successful","id":"b48b9be1-0e22-41d5-bd22-2a4bd4d9743e","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"signature","value":"<webhook-signature>","description":"<p>HMAC-SHA512 signature of the webhook payload, created with the OmniPay API key.</p>\n"}],"body":{"mode":"raw","raw":"{\n  \"event\": \"orderpayment.successful\",\n  \"data\": {\n    \"customerRef\": null,\n    \"userRef\": null,\n    \"walletBalance\": 0,\n    \"createdAt\": \"2026-07-31T18:00:00Z\",\n    \"walletPayment\": 3700000,\n    \"paylaterPayment\": 0,\n    \"promoPayment\": 0,\n    \"orderValue\": 3700000,\n    \"orderId\": \"SO_1001\",\n    \"loanId\": null,\n    \"transactionId\": \"TRX-OMN-2026-001234\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"https://example.com/webhooks/omnipay","description":"<p>Occurs after a bank transfer is confirmed and applied to the order. Verify the webhook signature before processing the payload.</p>\n<h2 id=\"event-data\">Event data</h2>\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>data.orderId</code></td>\n<td>Order identifier supplied when the order was created.</td>\n</tr>\n<tr>\n<td><code>data.orderValue</code></td>\n<td>Order amount in kobo.</td>\n</tr>\n<tr>\n<td><code>data.walletPayment</code></td>\n<td>Amount credited to the retailer's wallet in kobo.</td>\n</tr>\n<tr>\n<td><code>data.transactionId</code></td>\n<td>Unique OmniPay transaction identifier.</td>\n</tr>\n<tr>\n<td><code>data.createdAt</code></td>\n<td>Time the event was created.</td>\n</tr>\n</tbody>\n</table>\n</div><p>Find the order by <code>data.orderId</code>, verify the amounts, store <code>data.transactionId</code>, and mark the order as paid. Return HTTP <code>200</code> after the update is committed. If <code>transactionId</code> has already been processed, return HTTP <code>200</code> without applying the payment again.</p>\n","urlObject":{"host":["https://example.com/webhooks/omnipay"],"query":[],"variable":[]}},"response":[{"id":"2ca49433-cf76-40a4-8da4-778f1569151b","name":"200 - Acknowledged","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json"},{"key":"signature","value":"<webhook-signature>","description":"HMAC-SHA512 signature of the webhook payload, created with the OmniPay API key."}],"body":{"mode":"raw","raw":"{\n  \"event\": \"orderpayment.successful\",\n  \"data\": {\n    \"customerRef\": null,\n    \"userRef\": null,\n    \"walletBalance\": 0,\n    \"createdAt\": \"2026-07-31T18:00:00Z\",\n    \"walletPayment\": 3700000,\n    \"paylaterPayment\": 0,\n    \"promoPayment\": 0,\n    \"orderValue\": 3700000,\n    \"orderId\": \"SO_1001\",\n    \"loanId\": null,\n    \"transactionId\": \"TRX-OMN-2026-001234\"\n  }\n}","options":{"raw":{"language":"json"}}},"url":"https://example.com/webhooks/omnipay","description":"Occurs after a bank transfer is confirmed and applied to the order. Verify the webhook signature before processing the payload.\n\n## Event data\n\n| Field | Description |\n|---|---|\n| `data.orderId` | Order identifier supplied when the order was created. |\n| `data.orderValue` | Order amount in kobo. |\n| `data.walletPayment` | Amount credited to the retailer's wallet in kobo. |\n| `data.transactionId` | Unique OmniPay transaction identifier. |\n| `data.createdAt` | Time the event was created. |\n\nFind the order by `data.orderId`, verify the amounts, store `data.transactionId`, and mark the order as paid. Return HTTP `200` after the update is committed. If `transactionId` has already been processed, return HTTP `200` without applying the payment again."},"status":"OK","code":200,"_postman_previewlanguage":"Text","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"statusCode\": 200,\n  \"message\": \"Success\"\n}"}],"_postman_id":"b48b9be1-0e22-41d5-bd22-2a4bd4d9743e"}],"id":"500ba1c8-2aef-46cf-96a8-37ee44fbd3ef","_postman_id":"500ba1c8-2aef-46cf-96a8-37ee44fbd3ef","description":""}],"variable":[{"key":"omniPayApiBaseUrl","value":"https://api-dev.ompy.ng","type":"string","description":"Use https://api.ompy.ng in production."},{"key":"apiKey","value":"xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6","type":"string","description":"Development API key for https://api-dev.ompy.ng."},{"key":"walletPublicKey","value":"OMNIPUBKEY_FLX4HPQKKX124QBVQIKAAKSUNX4FIIXC","type":"string","description":"Development public key for the React Native Wallet SDK."},{"key":"referenceId","value":"customer_1001","type":"string","description":"Stable unique identifier assigned to the customer."},{"key":"phoneNumber","value":"08012345678","type":"string"},{"key":"emailAddress","value":"customer@example.com","type":"string"},{"key":"kycToken","value":"","type":"string","description":"Captured from the KYC session response; pass only this scoped token to Kyc.Onboarding."},{"key":"customerRef","value":"","type":"string","description":"OmniPay customer reference received in the KYC completion webhook."},{"key":"walletSessionId","value":"","type":"string","description":"Captured from the Wallet SDK session response and passed to the Wallet SDK."},{"key":"walletId","value":"","type":"string","description":"OmniPay wallet that receives the order payment."},{"key":"orderId","value":"SO_1001","type":"string","description":"Prefix the existing order ID with SO_; for example, SO_1001."},{"key":"amountKobo","value":"3700000","type":"string","description":"NGN 37,000.00 expressed in kobo."},{"key":"payerDisplayName","value":"Ada Customer","type":"string","description":"Letters and spaces only."},{"key":"orderIdempotencyKey","value":"","type":"string","description":"Idempotency key for order creation."},{"key":"dynamicAccountIdempotencyKey","value":"","type":"string","description":"Idempotency key for dynamic virtual account creation."},{"key":"yourWebhookUrl","value":"https://example.com/webhooks/omnipay","type":"string","description":"HTTPS webhook URL registered with OmniPay."}]}