{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"9ff096d2-310e-48f9-88ce-16bd5c20c621","name":"OmniPay API Reference","description":"OmniPay provides customer verification, wallet access, and payment collection through dynamic virtual accounts.\n\nKYC is the entry point. After a retailer completes verification, the `kyconboarding.completed` webhook returns:\n\n- `customerRef`, used to create a Wallet SDK session\n- `walletId`, used to direct an order payment to the retailer's wallet\n\n## KYC onboarding\n\nOmniPay KYC is available for web and React Native.\n\n### Create a KYC session\n\nCall **Create or resume KYC session** when the retailer starts verification. If the response status is `active`, render `Kyc.Onboarding` with the returned `token`. Reuse the same customer details to resume an unfinished session.\n\nThe SDK can request a replacement token after the initial token expires. The `getToken` callback must create or resume the same session and resolve with the new `token`.\n\n### React web\n\n```bash\nnpm install @omniretail/kyc-react-sdk\n```\n\n```tsx\nimport {Kyc} from '@omniretail/kyc-react-sdk';\nimport '@omniretail/kyc-react-sdk/styles.css';\n\n<Kyc.Onboarding\n  env=\"dev\"\n  token={kycToken}\n  getToken={refreshKycToken}\n  primaryColor=\"#A682FF\"\n  onComplete={refreshCustomerStatus}\n  onClose={() => history.back()}\n  onTokenExpired={restartVerification}\n  onError={error => reportErrorCode(error.code)}\n/>\n```\n\n### React Native\n\n```bash\nnpm 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```\n\n```tsx\nimport {Kyc} from '@omniretail/kyc-sdk';\n\n<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 => reportErrorCode(error.code)}\n/>\n```\n\n### Session props\n\n| Prop | Required | Description |\n|---|---:|---|\n| `env` | yes | `dev` or `prod`. Must match the KYC session environment. |\n| `token` | yes | Restricted token returned for an active KYC session. |\n| `getToken` | no | Async callback that resolves with a fresh token for the same session. |\n| `primaryColor` | no | Three- or six-digit hex colour. Defaults to `#A682FF`. |\n| `onComplete` | yes | Called when the retailer reaches the end of the KYC journey. |\n| `onClose` | yes | Called when the retailer closes KYC. |\n| `onTokenExpired` | no | Called when the SDK cannot refresh an expired token. |\n| `onError` | no | Receives the SDK error code and message. |\n\nTreat the `kyconboarding.completed` webhook as the final confirmation of verification.\n\nReact 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.\n\n## Wallet SDK\n\nDisplay a retailer's OmniPay wallet in a React Native application. The `Wallet` component opens in a native modal.\n\n### Create a session\n\nCreate a Wallet SDK session with the `customerRef` received in the KYC completion webhook. The response contains `data.sessionId`, which is passed to the component. Create a new session when it expires.\n\n### Install\n\n```bash\nnpm install @omniretail/wallet-sdk \\\n  react-native-webview react-native-device-info \\\n  react-native-select-contact react-native-share\n```\n\nRun CocoaPods on iOS, then rebuild the application.\n\n```bash\nnpx pod-install\n```\n\n### Render the wallet\n\n```tsx\nimport {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    <>\n      <Button title=\"Open wallet\" onPress={() => setWalletOpen(true)} />\n\n      {walletOpen ? (\n        <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={() => setWalletOpen(false)}\n        />\n      ) : null}\n    </>\n  );\n}\n```\n\n### Props\n\n| Prop | Required | Description |\n|---|---:|---|\n| `env` | yes | `dev` or `prod`. Must match the session environment. |\n| `publicKey` | yes | Public key for the selected environment. |\n| `customerRef` | yes | Value from `data.customerRef` in the KYC completion webhook. |\n| `sessionId` | yes | Value from `data.sessionId` in the Wallet SDK session response. |\n| `onClose` | yes | Called after the wallet modal closes. |\n| `primaryColor` | no | Three- or six-digit hex colour. Defaults to `#A682FF`. |\n| `features` | no | Controls access to airtime and data, bills, Paylater, and transfers. |\n| `onError` | no | Receives the SDK error code and message. |\n\n## Collect payment with a dynamic virtual account\n\nCollect 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.\n\n### Create a payment\n\n1. Create an order for the payment amount and set `metadata.receiverWalletId` to the retailer's `walletId`.\n2. Create a dynamic virtual account with the same `orderId` and amount.\n3. Show the returned bank name, account number, account name, amount, and expiry time.\n4. Confirm payment only after receiving `orderpayment.successful`.\n\nAmounts are sent in kobo. Both requests require `apiKey` and `IdempotencyKey` headers. Use a new idempotency key for each operation and retain it when retrying that operation.\n\n## Environments\n\n| Environment | API base URL | SDK `env` |\n|---|---|---|\n| Development | `https://api-dev.ompy.ng` | `dev` |\n| Production | `https://api.ompy.ng` | `prod` |\n\nCredentials and SDK sessions are specific to an environment.\n\n## Test credentials\n\n| Credential | Value |\n|---|---|\n| API key | `xrcQVg90ujKbUwUBytlrrHwxyds17yPo8JbBmK52IOzuLkBZYR26mqW06ZstCTr6` |\n| Wallet SDK public key | `OMNIPUBKEY_FLX4HPQKKX124QBVQIKAAKSUNX4FIIXC` |\n\nThese credentials are valid in the development environment. Production credentials are issued during go-live.\n\n## Authentication\n\nAuthenticate API requests with the `apiKey` header. API keys are secret and must never be included in web or mobile applications.\n\n```http\napiKey: {{apiKey}}\n```\n\n## Amounts\n\nAmounts are integer values in kobo. For example, NGN 37,000.00 is `3700000`.\n\n## Idempotent requests\n\nOrder and dynamic-account requests require an `IdempotencyKey` 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.\n\n## Webhooks\n\nRegister an HTTPS webhook URL with OmniPay before going live.\n\nEach webhook includes a `signature` 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.\n\n```js\nimport 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 &&\n    crypto.timingSafeEqual(received, expected);\n}\n\napp.post(\n  '/webhooks/omnipay',\n  express.raw({type: 'application/json'}),\n  async (req, res) => {\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```\n\nA webhook can be delivered more than once. Store the event before returning HTTP `200`, and make processing idempotent using `referenceId` or `transactionId`.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"56708741","team":7783923,"collectionId":"9ff096d2-310e-48f9-88ce-16bd5c20c621","publishedId":"2sBY4Tpctg","public":true,"publicUrl":"https://docs.ompy.ng","privateUrl":"https://go.postman.co/documentation/56708741-9ff096d2-310e-48f9-88ce-16bd5c20c621","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"light","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"FF6C37"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"}}]}},"version":"8.12.2","publishDate":"2026-07-31T18:56:55.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/5186b9722ac15449d0e97d720d28c8bd1e42318949dffb3bdcf7e2e359e5cacd","favicon":"https://ompy.ng/favicon.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://docs.ompy.ng/view/metadata/2sBY4Tpctg"}