{"info":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","description":"<html><head></head><body><p>Integrate airtime, mobile data, cable TV, electricity, betting wallet funding,<br>recharge-card e-PINs, data e-PINs, Smile, WAEC and JAMB into your application.</p>\n<p><strong>Base URL:</strong> <code>https://api.nellobytesystems.com/v1</code></p>\n<p>This collection documents the REST routes. Send JSON for POST requests and headers<br>for authentication. These URLs do not use the legacy <code>.asp?UserID=...&amp;APIKey=...</code><br>request format. Purchases and order lookups use the current-status contract below.</p>\n<h2 id=\"try-the-sandbox-in-postman\">Try the sandbox in Postman</h2>\n<p>Test 30 API operations with ₦100,000 in sandbox funds. The sandbox base URL is <code>https://sandbox-api.nellobytesystems.com/v1</code>.</p>\n<ol>\n<li>Open <a href=\"https://sandbox-api.nellobytesystems.com/signup/\">sandbox signup</a>, enter your email address, and select <strong>Create account</strong>. Follow the link in your email to open your dashboard. Returning users can select <strong>Sign in</strong>.</li>\n<li>Save your <code>sandboxUser</code> and <code>sandboxBearer</code> from the dashboard. <a href=\"https://sandbox-api.nellobytesystems.com/signup/postman\">Download the sandbox collection</a> and import it into Postman.</li>\n<li>In the sandbox collection’s <strong>Variables</strong> tab, enter both values locally and leave their shared values empty.</li>\n<li>Open <strong>Start here → Wallet balance</strong> and send <code>GET /v1/wallet</code>. A new account shows a balance of ₦100,000. Sandbox purchases use these test funds.</li>\n</ol>\n<p><a href=\"https://documenter.getpostman.com/view/11035265/2sBYHaMbeY\">Browse the sandbox API documentation</a> for the full list of requests and examples.</p>\n<h2 id=\"start-here\">Start here</h2>\n<ol>\n<li><p>Import this collection and the accompanying environment into Postman.</p>\n</li>\n<li><p>Select the <strong>Nellobyte REST v1 - Local credentials</strong> environment.</p>\n</li>\n<li><p>Set <code>memberId</code> and <code>apiKey</code> to your member ID and that member's <strong>standard API key</strong><br> in local variable values. Keep shared values empty. Never publish your credentials.</p>\n</li>\n<li><p>Send <strong>Health</strong> and then <strong>Wallet balance</strong>. A wallet response has <code>status: WALLET_SUCCESS</code>, <code>id</code>, <code>balance</code>, <code>currency</code> and an ISO date.</p>\n</li>\n<li><p>Load the relevant catalogue, select a valid code and fill the destination variables.<br> Verify the customer first where a verification endpoint exists.</p>\n</li>\n<li><p>For an intentional purchase, assign a new <code>requestId</code> and send that one order request.<br> Save its response and query its status using the same request ID or returned order ID.</p>\n</li>\n</ol>\n<p>The base URL is a production service. Purchase requests can debit a funded wallet.<br>Do not run the whole collection against a funded account. The collection contains no<br>automatic request chaining, purchase retries or scripts that transmit requests.</p>\n<h2 id=\"authentication\">Authentication</h2>\n<p>Every business endpoint requires both headers:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-http\">Authorization: Bearer \nX-User-ID: \nAccept: application/json\n\n</code></pre>\n<p>Postman's collection-level Bearer Token authorization supplies <code>Authorization</code>.<br>Each business request includes <code>X-User-ID</code>. <strong>Health</strong> uses no authentication.<br>Do not supply <code>UserID</code> or <code>APIKey</code> in the URL or JSON body. Use the member's standard<br>API key, not an app key or a provider/robot key. Existing account and IP access rules<br>continue to apply. Keep API keys on a trusted server rather than a public web page.</p>\n<h2 id=\"request-format\">Request format</h2>\n<p>POST requests require <code>Content-Type: application/json</code> and a flat JSON object.<br>Only documented fields are accepted; nested objects, arrays, null values, duplicate<br>fields and unknown fields are rejected. POST query-string parameters are rejected.<br>GET requests use query parameters where listed and must not have a body.<br>The maximum POST body is 65,536 bytes and each field value is limited to 8,192 characters.</p>\n<p>Use strings for identifiers, phone numbers and codes to preserve leading zeroes.<br>Supply monetary inputs in naira without currency signs or grouping commas.<br>Response amounts may be strings and may contain grouping commas. Date strings retain<br>the existing endpoint's format; they are not guaranteed to be ISO 8601 or UTC.</p>\n<h2 id=\"product-codes-and-prices\">Product codes and prices</h2>\n<p>Fetch current catalogues instead of hard-coding plan names, prices or limits.<br>For mobile data, use the selected network <code>ID</code> and plan <code>PRODUCT_CODE</code>. <code>DATA_TYPE</code><br>is <code>SME</code> or <code>DIRECT</code>; do not infer the delivery type from words in the plan name.<br>The same mobile-data catalogue supplies the plan identity for data e-PIN generation.<br>Smile uses its own package catalogue.</p>\n<h2 id=\"orders-and-uncertain-outcomes\">Orders and uncertain outcomes</h2>\n<p><code>RequestID</code> is required for every purchase: 1-64 letters, digits, underscores or hyphens.<br>Create one ID for one intended purchase and retain it with the returned order ID.<br>Do not change the ID or automatically submit another purchase after a timeout or 503.<br>First query <strong>Orders - by request ID</strong>. If the result is still unavailable, retain the<br>reference for investigation rather than assuming no debit occurred.</p>\n<p>REST response contract (20261102-3)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved<br>purchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a<br>saved completion returns ORDER_COMPLETED. Purchase and order lookups use the same<br>operational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.<br>Verification: status=VERIFIED, valid=true, customer_name, validation_reference.<br>An optional customer name/reference can be empty when the provider explicitly<br>confirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:<br>400 malformed request; 401 missing or invalid credentials; 403 blocked account,<br>IP restriction, HTTPS or KYC requirement; 404 owned order not found;<br>405 unsupported method; 413 oversized body; 415 unsupported content type;<br>422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;<br>429 rate limit with Retry-After: 1; 502 malformed provider response;<br>503 dependency or saved-state unavailable; 504 provider verification timeout.<br>An outage is not reported as an invalid customer. Raw provider error bodies and<br>credentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains<br>requestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable<br>post-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when<br>the save was confirmed. Query the same reference before another purchase. Never<br>automatically submit a purchase again because a response is 5xx or a lookup is 404.<br>ORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places<br>and no grouping commas. Dates are ISO 8601 with the database server's UTC offset,<br>for example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.<br>Cable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when<br>present, otherwise the authenticated member's phone. These phone fields accept<br>local 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase<br>requests/second, 10 verification requests/second, 60 authenticated-route GET<br>requests/second. Invalid credentials also consume the category limit. Health,<br>OPTIONS, documentation and private helper calls are excluded. Counters are bounded<br>in memory and reset on application recycle; this is not a distributed account<br>quota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-3 identifies this deployment.<br>Existing REST route names, request fields, standard key authentication, delivery mapping and commission are retained. New REST-only SQL objects protect<br>RequestID reuse and capture wallet snapshots. Shared legacy definitions are unchanged.<br>This response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>There is no working cancellation route in this REST release. <code>/orders/cancel</code><br>returns HTTP 501 <code>CANCELLATION_NOT_AVAILABLE</code> and is deliberately not a runnable request here.</p>\n<h2 id=\"http-request-errors\">HTTP request errors</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>HTTP</th>\n<th>Example status</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>400</td>\n<td><code>INVALID_JSON</code>, <code>UNKNOWN_PARAMETER</code>, <code>DUPLICATE_PARAMETER</code>, <code>USE_JSON_BODY_ONLY</code>, <code>GET_BODY_NOT_ALLOWED</code></td>\n<td>Correct the request format.</td>\n</tr>\n<tr>\n<td>401</td>\n<td><code>MISSING_CREDENTIALS</code>, <code>INVALID_CREDENTIALS</code>, <code>MISSING_USER_ID</code></td>\n<td>Check the authentication headers.</td>\n</tr>\n<tr>\n<td>403</td>\n<td><code>HTTPS_REQUIRED</code>, account/IP/KYC restriction</td>\n<td>Use HTTPS and review the member restriction.</td>\n</tr>\n<tr>\n<td>404</td>\n<td><code>ROUTE_NOT_FOUND</code></td>\n<td>Check the path.</td>\n</tr>\n<tr>\n<td>405</td>\n<td><code>METHOD_NOT_ALLOWED</code></td>\n<td>Use the documented HTTP method.</td>\n</tr>\n<tr>\n<td>413</td>\n<td><code>REQUEST_TOO_LARGE</code></td>\n<td>Reduce the body size.</td>\n</tr>\n<tr>\n<td>415</td>\n<td><code>JSON_CONTENT_TYPE_REQUIRED</code></td>\n<td>Send application/json.</td>\n</tr>\n<tr>\n<td>422</td>\n<td><code>MISSING_</code>, <code>INVALID_REQUEST_ID</code></td>\n<td>Supply a valid required value.</td>\n</tr>\n<tr>\n<td>503</td>\n<td>Service or outcome unavailable</td>\n<td>Query an uncertain purchase before considering another order.</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"examples\">Examples</h2>\n<p>All saved responses marked <strong>Illustrative</strong> are synthetic, source-derived format examples.<br>They are not live transaction results or current price quotations. Catalogue examples<br>show only a subset of entries. PINs, tokens, IDs and customer details are placeholders.<br>Refresh the real catalogue with your account before an intentional purchase.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated<br>member and RequestID. Keep the same route and field values for an identical retry.<br>JSON property order and property-name casing do not affect identity. Missing and<br>empty optional fields are equivalent; different supplied field values (including<br>numeric spellings, Memo and callback URL) are conservatively treated as a conflict.<br>The database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without<br>another purchase. Idempotent-Replayed: true identifies a replay. Changed details<br>or another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.<br>A request still processing, interrupted, or with uncertain save outcome returns<br>HTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or<br>contact support; do not replace the RequestID to work around that response.<br>Requests rejected before purchase SQL retain their rejection. Corrected purchases<br>use a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,<br>decimal strings describing the saved request's wallet snapshots. They are captured<br>inside the purchase transaction and exposed only after commit, including batches.<br>They describe the original purchase, not the customer's current wallet after later<br>activity or a refund. GET /wallet remains the current wallet observation.<br>For an older airtime request adopted by its existing replay mechanism, unavailable<br>historical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,<br>those writes roll back while the initial pending claim is retained for review.<br>There is no automatic claim expiry or repeat purchase after an ambiguous failure.<br>An old receipt cannot be reused just because its operational record is no longer available:<br>the receipt persists, and unavailable current status returns 503 with saved=true.<br>Retained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior<br>unconfirmed requests and legacy endpoints are not backfilled into this ledger.<br>Do not re-submit a pre-deployment uncertain request; reconcile its saved payment.<br>Existing pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n<p>For an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.</p>\n<h3 id=\"request-reference\">Request reference</h3>\n<p>Responses generated by the REST runtime include an X-Request-Reference header. Give this reference to support when investigating a request. It identifies an HTTP attempt; continue using RequestID for purchase idempotency. Static files, IIS-generated responses and failures before the runtime starts may not include this header.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"11035265","collectionId":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","publishedId":"2sBYHaNGXy","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-11-11T19:27:27.000Z"},"item":[{"name":"Start here","item":[{"name":"Health","id":"8879f073-1faf-4f5a-841b-2679bb506f6d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"noauth","isInherited":false},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/health","description":"<p>Unauthenticated runtime health check. <code>scope: runtime-only</code> does not test database access, provider connectivity or purchase processing.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","urlObject":{"path":["health"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"fbd58e26-38e0-44ad-b9cb-ea99507e455e","name":"Healthy runtime","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/health"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"OK\",\n  \"version\": \"rest-v1\",\n  \"scope\": \"runtime-only\"\n}"}],"_postman_id":"8879f073-1faf-4f5a-841b-2679bb506f6d"},{"name":"Wallet balance","id":"948bd683-3643-4fba-9e25-a05cb4a834f4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/wallet","description":"<p>Current wallet snapshot.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["wallet"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"7bab39f7-7a31-4cc4-9bd8-d8111c7ab702","name":"Illustrative success","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/wallet"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"WALLET_SUCCESS\",\n  \"id\": \"EXAMPLE_MEMBER\",\n  \"phoneno\": \"EXAMPLE_PHONE\",\n  \"balance\": \"1000.00\",\n  \"currency\": \"NGN\",\n  \"date\": \"2026-11-02T12:00:00+01:00\"\n}"}],"_postman_id":"948bd683-3643-4fba-9e25-a05cb4a834f4"},{"name":"e-PIN order - status only (no PIN values)","id":"f28338a3-c286-416a-aaa7-6fcbba7870e1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/orders?OrderID=&IncludePINs=false","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>For an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"key":"OrderID","value":""},{"key":"IncludePINs","value":"false"}],"variable":[]}},"response":[{"id":"4b687a44-9d25-402f-8ce6-ea3cbd0a843a","name":"Pending PIN generation","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=&IncludePINs=false","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":""},{"key":"IncludePINs","value":"false"}]},"description":"Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.\n\nEvery successfully read order has `status`, `orderid`, `transactionid`, `requestid`, `transactiondate`, `producttype`, `productname`, `amount`, `walletbalance`, `paymentoption` and `remark`, plus product-specific details. Empty detail fields are empty strings. `remark` is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. `amount` uses the saved debit where present, and `amountcredited` describes a positive saved credit (not cashback).\n\n| Status | Meaning |\n| --- | --- |\n| ORDER_RECEIVED | Saved Paid state; delivery not yet confirmed. |\n| ORDER_PENDING | Saved Pending state. |\n| ORDER_PROCESSING | Processing, or awaiting the final completion receipt. |\n| ORDER_PROCESSED | Saved Processed state; not equivalent to Completed. |\n| ORDER_COMPLETED | Saved Completed state with no pending completion marker. |\n| ORDER_REFUNDED | Saved Refunded state. |\n| ORDER_CANCELLED | Saved Cancelled state. |\n| ORDER_FAILED | Saved Failed state; this response does not itself refund anything. |\n| ORDER_FINISHED_WITH_FAILURES | All children finished, with mixed completed/refunded/cancelled/failed states. |\n| ORDER_STATUS_UNAVAILABLE | Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response. |\n| ORDER_NOT_FOUND | No owned order was found for the supplied selector. This does not prove no earlier payment occurred. |\n\nAn unavailable post-purchase read retains `orderid`, `requestid`, and `saved: true`. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.\n\nFor a multi-phone airtime request, the top-level status covers the entire request and `orders` contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.\n\ne-PIN orders retain `TXN_EPIN` or `TXN_EPIN_DATABUNDLE` when their complete owned batch is available, together with `ORDER_ID` and `detailsstatus: AVAILABLE`. `detailsstatus: PENDING` or `UNAVAILABLE` does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.\n\nREST response contract (20261102-2)\n\nSuccessful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.\n\nWallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.\n\nErrors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.\n\nIf a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.\n\nWallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.\n\nLimits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.\n\nThe response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.\n\n\nFor an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.\n\ne-PIN asynchronous responses (20261103-1)\n\nPOST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.\n\nGET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.\n\nGET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.\n\nPoll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.\n\nFor large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.\n\nepin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.\n"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"Retry-After","value":"5"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_RECEIVED\",\n  \"orderid\": \"123\",\n  \"transactionid\": \"123\",\n  \"requestid\": \"example-epin-001\",\n  \"detailsstatus\": \"PENDING\",\n  \"status_url\": \"/v1/orders?OrderID=123&IncludePINs=false\",\n  \"pins_url\": \"/v1/orders?OrderID=123&IncludePINs=true\",\n  \"retry_after_seconds\": 5\n}"},{"id":"2a427db4-de04-4b0d-92ab-05e68a2d3514","name":"Ready - retrieve pins_url with the same member credentials","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=&IncludePINs=false","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":""},{"key":"IncludePINs","value":"false"}]},"description":"Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.\n\nEvery successfully read order has `status`, `orderid`, `transactionid`, `requestid`, `transactiondate`, `producttype`, `productname`, `amount`, `walletbalance`, `paymentoption` and `remark`, plus product-specific details. Empty detail fields are empty strings. `remark` is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. `amount` uses the saved debit where present, and `amountcredited` describes a positive saved credit (not cashback).\n\n| Status | Meaning |\n| --- | --- |\n| ORDER_RECEIVED | Saved Paid state; delivery not yet confirmed. |\n| ORDER_PENDING | Saved Pending state. |\n| ORDER_PROCESSING | Processing, or awaiting the final completion receipt. |\n| ORDER_PROCESSED | Saved Processed state; not equivalent to Completed. |\n| ORDER_COMPLETED | Saved Completed state with no pending completion marker. |\n| ORDER_REFUNDED | Saved Refunded state. |\n| ORDER_CANCELLED | Saved Cancelled state. |\n| ORDER_FAILED | Saved Failed state; this response does not itself refund anything. |\n| ORDER_FINISHED_WITH_FAILURES | All children finished, with mixed completed/refunded/cancelled/failed states. |\n| ORDER_STATUS_UNAVAILABLE | Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response. |\n| ORDER_NOT_FOUND | No owned order was found for the supplied selector. This does not prove no earlier payment occurred. |\n\nAn unavailable post-purchase read retains `orderid`, `requestid`, and `saved: true`. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.\n\nFor a multi-phone airtime request, the top-level status covers the entire request and `orders` contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.\n\ne-PIN orders retain `TXN_EPIN` or `TXN_EPIN_DATABUNDLE` when their complete owned batch is available, together with `ORDER_ID` and `detailsstatus: AVAILABLE`. `detailsstatus: PENDING` or `UNAVAILABLE` does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.\n\nREST response contract (20261102-2)\n\nSuccessful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.\n\nWallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.\n\nErrors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.\n\nIf a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.\n\nWallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.\n\nLimits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.\n\nThe response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.\n\n\nFor an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.\n\ne-PIN asynchronous responses (20261103-1)\n\nPOST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.\n\nGET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.\n\nGET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.\n\nPoll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.\n\nFor large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.\n\nepin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.\n"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"123\",\n  \"transactionid\": \"123\",\n  \"requestid\": \"example-epin-001\",\n  \"detailsstatus\": \"AVAILABLE\",\n  \"status_url\": \"/v1/orders?OrderID=123&IncludePINs=false\",\n  \"pins_url\": \"/v1/orders?OrderID=123&IncludePINs=true\",\n  \"ORDER_ID\": \"123\"\n}"}],"_postman_id":"f28338a3-c286-416a-aaa7-6fcbba7870e1"},{"name":"Orders - by request ID","id":"447f29f7-2710-4896-986c-80924796f12f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/orders?RequestID=","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>For an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"description":{"content":"<p>Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries.</p>\n","type":"text/plain"},"key":"RequestID","value":""}],"variable":[]}},"response":[{"id":"4c275249-09e8-4a36-a026-0d3472899f74","name":"Illustrative current saved completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?RequestID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"RequestID","value":"","description":"Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"910fd7af-04d4-473a-87fc-42ea0ebb00ee","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?RequestID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"RequestID","value":"","description":"Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries."}]}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"84112291-680f-4642-8093-c9e45fcdc5fc","name":"No matching operational order / outside lookup window","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?RequestID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"RequestID","value":"","description":"Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries."}]}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_NOT_FOUND\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\"\n}"},{"id":"2e2ea41e-ecb2-46dd-9e6c-00771e2f4225","name":"Illustrative current pending completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?RequestID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"RequestID","value":"","description":"Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"f9c58ae6-3ac2-40fb-800f-89e213924bdf","name":"Current status unavailable - query existing reference","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?RequestID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"RequestID","value":"","description":"Your unique purchase reference: 1-64 ASCII letters, digits, underscores or hyphens. Keep it for subsequent status queries."}]}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"447f29f7-2710-4896-986c-80924796f12f"},{"name":"Orders - by PIN batch","id":"7af19325-224f-4b7a-9dba-2996e95016bf","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/orders?BatchNo=","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>For an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"description":{"content":"<p>Batch reference from a generated PIN batch.</p>\n","type":"text/plain"},"key":"BatchNo","value":""}],"variable":[]}},"response":[{"id":"aeffb1c2-e014-4097-9844-d3a2e64c0045","name":"Illustrative current saved completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?BatchNo=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"BatchNo","value":"","description":"Batch reference from a generated PIN batch."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"EXAMPLE_BATCH\",\n  \"TXN_EPIN\": [\n    {\n      \"transactionid\": \"EXAMPLE_ORDER_ID\",\n      \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n      \"batchno\": \"EXAMPLE_BATCH\",\n      \"mobilenetwork\": \"MTN\",\n      \"sno\": \"EXAMPLE_SERIAL\",\n      \"pin\": \"EXAMPLE_PIN_NOT_VALID\",\n      \"amount\": \"100\"\n    }\n  ],\n  \"detailsstatus\": \"AVAILABLE\",\n  \"ORDER_ID\": \"EXAMPLE_ORDER_ID\"\n}"},{"id":"ac3af8c8-7144-43d4-bab2-1726438aac66","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?BatchNo=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"BatchNo","value":"","description":"Batch reference from a generated PIN batch."}]}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"bca0f28d-b266-49e4-901d-761e750e9c29","name":"No matching operational order / outside lookup window","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?BatchNo=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"BatchNo","value":"","description":"Batch reference from a generated PIN batch."}]}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_NOT_FOUND\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\"\n}"},{"id":"5e25f9b7-f551-45a8-982b-52ff6f563b37","name":"Illustrative current pending completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?BatchNo=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"BatchNo","value":"","description":"Batch reference from a generated PIN batch."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"EXAMPLE_BATCH\",\n  \"detailsstatus\": \"PENDING\"\n}"},{"id":"77b3da44-6d3c-48d3-9216-ae49bee36c59","name":"Current status unavailable - query existing reference","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?BatchNo=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"BatchNo","value":"","description":"Batch reference from a generated PIN batch."}]}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"7af19325-224f-4b7a-9dba-2996e95016bf"},{"name":"Orders - by order ID","id":"48612d7a-a357-49b1-95e8-ee3ca4f49afe","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/orders?OrderID=","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>For an older order, use GET /orders?OrderID=YOUR_ORDER_ID. The same response fields and status names apply. Current saved order details take precedence; when the order is no longer in the active retention window, its retained transaction details can be displayed. This is an individual order view, not a batch reconstruction. RequestID and BatchNo lookups, purchase results and request replay protection keep their existing operational rules. A database error returns ORDER_STATUS_UNAVAILABLE; it is not treated as a missing order. Viewing a receipt never authorizes a refund, redo or wallet movement.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"description":{"content":"<p>Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate.</p>\n","type":"text/plain"},"key":"OrderID","value":""}],"variable":[]}},"response":[{"id":"0552704d-a781-4cf3-b354-dc09ea9edafd","name":"Illustrative current saved completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":"","description":"Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"f20e10c2-1666-4237-9a56-b84581c6be2e","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":"","description":"Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate."}]}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"041a9438-c073-4476-9aea-5ecaf4e86d9b","name":"No matching operational order / outside lookup window","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":"","description":"Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate."}]}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_NOT_FOUND\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\"\n}"},{"id":"22ffd780-0309-4374-9aea-069d2ae8133a","name":"Illustrative current pending completion","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":"","description":"Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate."}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"47c3063f-2f5c-4129-89c1-dd57ad8760c5","name":"Current status unavailable - query existing reference","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/orders?OrderID=","host":["https://api.nellobytesystems.com/v1"],"path":["orders"],"query":[{"key":"OrderID","value":"","description":"Order identifier returned by the original purchase; use orderid, transactionid or ORDER_ID as appropriate."}]}},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"48612d7a-a357-49b1-95e8-ee3ca4f49afe"},{"name":"Search transaction history","id":"167b9f0e-e8a1-4066-8d24-e8a2d2348409","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/transactions?date_from=2026-10-01&date_to=2026-10-31&limit=50","description":"<p>Search your retained transaction summaries. Both date_from and date_to are required. Each request covers at most 31 days, including any older retained month. Date-only YYYY-MM-DD values use Nigerian time (UTC+01:00); date_to includes that whole day. Timestamps use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss+HH:mm, with mandatory seconds and timezone, no fractional seconds. Encode a plus sign as %2B. Timestamp start is inclusive and end is exclusive. Returned date_from/date_to are normalized Nigerian timestamps with an exclusive end.</p>\n<p>Default limit 50, maximum 100. Results are newest first by date and transaction ID. count is this page only; no total count or page number. Supply next_cursor unchanged along with the same dates to get the next page; limit may change. A cursor cannot be reused for another member or date range. has_more=false returns next_cursor=\"\". An empty search succeeds with HTTP 200, TRANSACTIONS_SUCCESS and transactions=[].</p>\n<p>This is a display-only summary search. It does not requery a provider, retry delivery, move a wallet or authorize refunds/redo. It may briefly lag recent operations. No PINs, tokens, remarks or product names are included in the list; use GET /orders?OrderID=... for individual details. amountcharged is the signed saved movement (negative debit, positive credit); walletbalance is the saved historical balance, not the current wallet. Monetary fields are decimal strings with two places, or an empty string if unavailable. productid/serviceid/variationid/providerid are saved history identifiers, not necessarily purchase catalogue codes. Unknown saved statuses return ORDER_STATUS_UNAVAILABLE, never an invented completion.</p>\n<p>Pagination is a live view, not a frozen export: late history updates or date corrections may change earlier pages. Start a fresh search to include such changes. Limits include the existing GET rate gate and an additional 2 history searches/second per authenticated member per IIS worker. These counters reset on recycle and are not a distributed quota. HTTP 429 includes Retry-After. Invalid ranges/limits/cursors return 422. An unavailable reader or timeout returns 503, not an empty successful result. No internal storage names appear in the response.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["transactions"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"key":"date_from","value":"2026-10-01"},{"key":"date_to","value":"2026-10-31"},{"key":"limit","value":"50"},{"disabled":true,"description":{"content":"<p>Paste next_cursor from the previous page; keep the same dates.</p>\n","type":"text/plain"},"key":"cursor","value":""}],"variable":[]}},"response":[],"_postman_id":"167b9f0e-e8a1-4066-8d24-e8a2d2348409"},{"name":"Current API commission rates","id":"c609ae29-2275-4a4b-b750-56cb84c4f480","request":{"method":"GET","header":[{"key":"X-User-ID","value":""},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/commission-rates","description":"<p>All standard API commission rates in one JSON response: airtime, mobile databundle plans, recharge-card e-PINs and bills/services. No format flag, category selector or request body is needed. Uses this REST version's own pricing readers and plan catalogue, with no call to the main website. Rates are independent of membership; account-specific partner e-PIN prices can differ. Data e-PIN generation is excluded and retains its own checkout quotation.</p>\n<p>Money and percentages in this response are JSON numbers (not formatted strings). wallet_debit is the amount charged upfront, benefit_after_success is credited after successful completion, and net_cost is their difference. A percentage of 4 means 4%, not 0.04. The observation time is UTC; this is not a price reservation or an atomic snapshot across all products. Purchase validation remains authoritative.</p>\n<p>HTTP 200 / RATES_SUCCESS means all categories loaded. HTTP 503 / RATES_PARTIAL or RATES_UNAVAILABLE means some or all rates are unavailable; unavailable monetary/rate fields are null, never a fabricated zero. Only use items marked AVAILABLE. A configuration failure can return a status/message without categories. Keep X-Request-Reference for support.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["commission-rates"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[],"_postman_id":"c609ae29-2275-4a4b-b750-56cb84c4f480"}],"id":"a9e16323-42e4-485a-a018-e03c56c176bb","description":"<p>Check runtime health, inspect your wallet and look up orders. Start with Health, then Wallet balance.</p>\n","_postman_id":"a9e16323-42e4-485a-a018-e03c56c176bb","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Airtime","item":[{"name":"Airtime networks and discounts","id":"ec64b3f9-fc91-4191-8e9b-691d81cf6f9d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/airtime/networks","description":"<p>Read <code>MOBILE_NETWORK[]</code>. Use <code>NETWORK_ID</code> as <code>MobileNetwork</code>; read <code>MINAMOUNT</code>, <code>MAXAMOUNT</code> and available <code>BONUS</code> codes from this response.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["airtime","networks"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"1cf63b8e-a2a3-4c61-aa00-e779a11fa400","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/airtime/networks"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"MOBILE_NETWORK\": [\n    {\n      \"NETWORK_NAME\": \"MTN\",\n      \"NETWORK_ID\": \"01\",\n      \"DISCOUNT_AMOUNT\": \"1.000\",\n      \"DISCOUNT\": \"0%\",\n      \"MINAMOUNT\": 50,\n      \"MAXAMOUNT\": 200000,\n      \"BONUS\": [\n        {\n          \"BONUS_CODE\": \"03\",\n          \"BONUS_NAME\": \"GistPlus (400% airtime bonus)\"\n        }\n      ]\n    }\n  ]\n}"},{"id":"bb69046d-989b-4aed-9412-b81c073997ad","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/airtime/networks"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"ec64b3f9-fc91-4191-8e9b-691d81cf6f9d"},{"name":"Buy airtime","id":"a4391167-97fa-47b5-b481-8031b9c3ee8c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","airtime"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"5cdf5f02-f31b-4fec-a2a3-642f20bf8bc3","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"ab4d12c5-5e22-4b91-8023-379a8bb122f3","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"3b5b22e3-e417-4d51-87ae-d243bb698e15","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"564fa2b2-38d0-41cd-88b9-1dde8e17bdc4","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"e06ac06b-f16d-4af4-a160-d52a5ecbbf73","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Amount\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/airtime"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"a4391167-97fa-47b5-b481-8031b9c3ee8c"}],"id":"1ac9e0e6-6a32-4f88-b00a-1fccadbc501e","description":"<p>Load the network catalogue, choose a network and submit airtime to a phone number. Optional bonus codes come from that catalogue.</p>\n","_postman_id":"1ac9e0e6-6a32-4f88-b00a-1fccadbc501e","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Mobile data","item":[{"name":"Data networks and discounts","id":"eb3065be-9c08-447b-b0f7-e2e2429face9","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/networks","description":"<p>Read <code>MOBILE_NETWORK[]</code> and use <code>NETWORK_ID</code> as <code>MobileNetwork</code>.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["databundle","networks"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"7b8fb91a-4c72-41db-a0d6-12c61a49fd67","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/networks"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"MOBILE_NETWORK\": [\n    {\n      \"NETWORK_NAME\": \"MTN\",\n      \"NETWORK_ID\": \"01\",\n      \"DISCOUNT_AMOUNT\": \"1.000\",\n      \"DISCOUNT\": \"0%\"\n    }\n  ]\n}"},{"id":"7106dc12-359f-4468-861a-ea9cc145e97a","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/networks"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"eb3065be-9c08-447b-b0f7-e2e2429face9"},{"name":"Data plans and discounts","id":"3005faeb-0bc8-40b3-8ec0-9322f83eacc7","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/plans","description":"<p>Read <code>MOBILE_NETWORK.&lt;network&gt;[].PRODUCT[]</code>. Select the network <code>ID</code> and plan <code>PRODUCT_CODE</code>, <code>PRODUCT_NAME</code>, <code>PRODUCT_AMOUNT</code> and <code>DATA_TYPE</code>. The response may also contain <code>PRODUCT_ID</code> and discount fields; new integrations should send <code>PRODUCT_CODE</code> as <code>DataPlan</code>. No network filter query is accepted; select the network from the returned catalogue.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["databundle","plans"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"1bedc994-8fcd-4096-b6c5-1029f0cf4262","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/plans"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"MOBILE_NETWORK\": {\n    \"MTN\": [\n      {\n        \"ID\": \"01\",\n        \"PRODUCT\": [\n          {\n            \"PRODUCT_SNO\": \"1\",\n            \"PRODUCT_CODE\": \"2\",\n            \"PRODUCT_ID\": \"500\",\n            \"PRODUCT_NAME\": \"500MB - Weekly (SME)\",\n            \"PRODUCT_AMOUNT\": \"300\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"1\",\n            \"PRODUCT_DISCOUNT\": \"0%\",\n            \"DATA_TYPE\": \"SME\"\n          },\n          {\n            \"PRODUCT_SNO\": \"11\",\n            \"PRODUCT_CODE\": \"38\",\n            \"PRODUCT_ID\": \"100.01\",\n            \"PRODUCT_NAME\": \"110MB Daily Plan - 1 day (Awoof Data)\",\n            \"PRODUCT_AMOUNT\": \"100\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"1\",\n            \"PRODUCT_DISCOUNT\": \"0%\",\n            \"DATA_TYPE\": \"DIRECT\"\n          }\n        ]\n      }\n    ],\n    \"Glo\": [\n      {\n        \"ID\": \"02\",\n        \"PRODUCT\": []\n      }\n    ],\n    \"m_9mobile\": [\n      {\n        \"ID\": \"03\",\n        \"PRODUCT\": []\n      }\n    ],\n    \"Airtel\": [\n      {\n        \"ID\": \"04\",\n        \"PRODUCT\": []\n      }\n    ]\n  }\n}"},{"id":"c0d3f1a5-8372-4bc3-ab5f-d72c033f6b23","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/plans"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"823f0f8d-e752-4a2b-b701-ba0387fba695","name":"Catalogue unavailable","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/databundle/plans"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"CATALOGUE_PRICE_UNAVAILABLE\",\n  \"message\": \"catalogue price unavailable\"\n}"}],"_postman_id":"3005faeb-0bc8-40b3-8ec0-9322f83eacc7"},{"name":"Buy data bundle","id":"fb94401b-57c1-4521-bcb6-fa0d2c37cb15","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","databundle"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"674e5b84-d6b3-472a-8fbf-0091e755ce60","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Product\",\n  \"productname\": \"500MB - Weekly (SME)\",\n  \"amount\": \"300.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"f7a5bb61-8695-4967-849f-0cf9d7df6cb1","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"189c2e97-e248-4e51-b6a4-28ec712dbf7a","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"e1babb6a-97a0-4dac-a986-f266d518b142","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Product\",\n  \"productname\": \"500MB - Weekly (SME)\",\n  \"amount\": \"300.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"cb56c632-0e6b-427c-b030-c0422da55a76","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"fb94401b-57c1-4521-bcb6-fa0d2c37cb15"}],"id":"af9ee6e1-8931-47aa-afc1-98ab5b79bccb","description":"<p>Load networks and plans. Use PRODUCT_CODE within the selected network; DATA_TYPE explicitly distinguishes SME and DIRECT.</p>\n","_postman_id":"af9ee6e1-8931-47aa-afc1-98ab5b79bccb","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Cable TV","item":[{"name":"Cable TV providers","id":"d6498329-56df-46ff-b146-8c5f7074e9a3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/providers","description":"<p>Read <code>CABLE_TV[]</code> and use <code>TV_ID</code> as <code>CableTV</code>. A provider being listed does not imply every verification path supports every provider; verification currently accepts DSTV, GOTV and Startimes.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["cabletv","providers"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"7dbdbe06-b21b-4b78-b6f1-1713f2961b71","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/providers"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"CABLE_TV\": [\n    {\n      \"TV_NAME\": \"DSTV\",\n      \"TV_ID\": \"dstv\",\n      \"DISCOUNT_AMOUNT\": \"1.000\",\n      \"DISCOUNT\": \"0%\"\n    }\n  ]\n}"},{"id":"9e63ede7-dd07-4e0f-9f6c-5b393a0387f7","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/providers"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"d6498329-56df-46ff-b146-8c5f7074e9a3"},{"name":"Cable TV packages","id":"22576854-d8eb-4ce7-ba10-eb364ad1560b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/packages","description":"<p>Read <code>TV_ID.&lt;provider&gt;[].PRODUCT[]</code> and select <code>PACKAGE_ID</code> as <code>Package</code>. Match the package to its provider and read the current <code>PACKAGE_AMOUNT</code>.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["cabletv","packages"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"9fb4be0a-1d7d-4bee-9ddd-16e116bef50f","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/packages"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"TV_ID\": {\n    \"DStv\": [\n      {\n        \"ID\": \"dstv\",\n        \"PRODUCT\": [\n          {\n            \"PACKAGE_ID\": \"EXAMPLE_PACKAGE\",\n            \"PACKAGE_NAME\": \"Example package\",\n            \"PACKAGE_AMOUNT\": \"5000\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"5000\",\n            \"PRODUCT_DISCOUNT\": \"0\",\n            \"MINAMOUNT\": 100,\n            \"MAXAMOUNT\": 200000\n          }\n        ]\n      }\n    ]\n  }\n}"},{"id":"f1f2028c-5dcc-4727-b0a9-036a5c385776","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/cabletv/packages"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"22576854-d8eb-4ce7-ba10-eb364ad1560b"},{"name":"Buy cable TV subscription","id":"03b230f3-1bbb-47d1-9443-415a45f5ed99","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","cabletv"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"8883c0b7-d9c6-48f4-bf44-1ff8ce7c0595","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"CableTV\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"EXAMPLE_SMARTCARD\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"ebef7284-309e-438b-8844-de7fd1b5b54c","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"e1849c11-689e-4fb6-9d37-b84975eaed0d","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"a67396a9-eb62-419a-9293-5ffaf49f1609","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"CableTV\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"EXAMPLE_SMARTCARD\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"600544b7-d80e-4532-8ab9-694d95533f51","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"Package\": \"\",\n  \"SmartCardNo\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/cabletv"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"03b230f3-1bbb-47d1-9443-415a45f5ed99"},{"name":"Verify cable TV smart card","id":"9fca4490-1992-4378-98ff-bb5e80288ec6","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv","description":"<p>Read-only provider verification. No purchase is made.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["verify","cabletv"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"dfeffca7-925e-4f00-8289-7fafceeb11e9","name":"Illustrative success","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFIED\",\n  \"valid\": true,\n  \"customer_name\": \"Example customer\",\n  \"validation_reference\": \"\"\n}"},{"id":"fe269796-dacf-40a6-ab79-96d86eb10705","name":"VERIFICATION_REJECTED","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFICATION_REJECTED\",\n  \"message\": \"verification rejected\",\n  \"valid\": false\n}"},{"id":"396bd89e-ee04-4703-a637-9839bbc87f84","name":"INVALID_PROVIDER_RESPONSE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv"},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"INVALID_PROVIDER_RESPONSE\",\n  \"message\": \"invalid provider response\"\n}"},{"id":"1901759c-9f7a-4065-a2d6-9b1891086001","name":"PROVIDER_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_UNAVAILABLE\",\n  \"message\": \"provider unavailable\"\n}"},{"id":"b1c7b788-8e46-4562-a0b0-29008435fad8","name":"PROVIDER_TIMEOUT","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"CableTV\": \"\",\n  \"SmartCardNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/cabletv"},"status":"Gateway Timeout","code":504,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_TIMEOUT\",\n  \"message\": \"provider timeout\"\n}"}],"_postman_id":"9fca4490-1992-4378-98ff-bb5e80288ec6"}],"id":"3ac5dc61-366e-41ce-aea8-c02609e7746e","description":"<p>Load providers and packages, verify the smart-card number, then place an order with the matching provider and package.</p>\n","_postman_id":"3ac5dc61-366e-41ce-aea8-c02609e7746e","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Electricity","item":[{"name":"Electricity discos","id":"5e740136-39c5-44e8-b8aa-2d99546fa473","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/electricity/discos","description":"<p>Read <code>ELECTRIC_COMPANY.&lt;company&gt;[]</code>. Use the company <code>ID</code> as <code>ElectricCompany</code> and select prepaid or postpaid from <code>PRODUCT</code>. Read current <code>MINAMOUNT</code> and <code>MAXAMOUNT</code>; providers can impose additional restrictions.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["electricity","discos"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"2b167fc4-cc05-445c-944a-9f3009df624e","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/electricity/discos"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"ELECTRIC_COMPANY\": {\n    \"EKO_ELECTRIC\": [\n      {\n        \"ID\": \"01\",\n        \"NAME\": \"Eko Electric - EKEDC\",\n        \"PRODUCT\": [\n          {\n            \"PRODUCT_ID\": \"01\",\n            \"PRODUCT_TYPE\": \"prepaid\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"1\",\n            \"PRODUCT_DISCOUNT\": \"0%\",\n            \"MINAMOUNT\": 1000,\n            \"MAXAMOUNT\": 200000\n          },\n          {\n            \"PRODUCT_ID\": \"02\",\n            \"PRODUCT_TYPE\": \"postpaid\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"1\",\n            \"PRODUCT_DISCOUNT\": \"0%\",\n            \"MINAMOUNT\": 1000,\n            \"MAXAMOUNT\": 200000\n          }\n        ]\n      }\n    ]\n  }\n}"},{"id":"3d6828e9-5841-4ab2-9600-47abac1546dd","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/electricity/discos"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"5e740136-39c5-44e8-b8aa-2d99546fa473"},{"name":"Buy electricity","id":"3d5581d3-82ff-4edf-b1df-224b947e32ae","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","electricity"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"de2bda07-7ec9-4036-a540-4a3f51e8b272","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Electricity\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"EXAMPLE_METER\",\n  \"metertoken\": \"EXAMPLE_TOKEN_NOT_VALID\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"3782d371-2a33-448a-8fdb-68966244efe3","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"ed8c4849-18a4-47eb-ae86-fd676c54bf18","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"495c85b9-5923-42af-93a9-4d055a46e699","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Electricity\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"EXAMPLE_METER\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"d33b73a6-ec73-4229-9bbf-b0d1e3035332","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\",\n  \"PhoneNo\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/electricity"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"3d5581d3-82ff-4edf-b1df-224b947e32ae"},{"name":"Verify electricity meter","id":"b03507f5-a756-475a-ae86-4ee23695ddd2","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity","description":"<p>Read-only provider verification. No purchase is made.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["verify","electricity"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"60b2c591-8cd3-4245-a97c-d290adbf33cc","name":"Illustrative success","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFIED\",\n  \"valid\": true,\n  \"customer_name\": \"Example customer\",\n  \"validation_reference\": \"\"\n}"},{"id":"9aadf20a-6c3e-49ef-bb26-c25285682045","name":"VERIFICATION_REJECTED","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFICATION_REJECTED\",\n  \"message\": \"verification rejected\",\n  \"valid\": false\n}"},{"id":"3c336449-72f0-4c4d-89e0-3c0dc30b73f9","name":"INVALID_PROVIDER_RESPONSE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity"},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"INVALID_PROVIDER_RESPONSE\",\n  \"message\": \"invalid provider response\"\n}"},{"id":"50e02502-e2a3-4c10-94f0-3800cbdecb5d","name":"PROVIDER_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_UNAVAILABLE\",\n  \"message\": \"provider unavailable\"\n}"},{"id":"ae416a1b-094d-435e-ba69-716d3e2833b1","name":"PROVIDER_TIMEOUT","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ElectricCompany\": \"\",\n  \"MeterNo\": \"\",\n  \"MeterType\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/electricity"},"status":"Gateway Timeout","code":504,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_TIMEOUT\",\n  \"message\": \"provider timeout\"\n}"}],"_postman_id":"b03507f5-a756-475a-ae86-4ee23695ddd2"}],"id":"ff8e412d-adf4-415f-a3d0-59d0a4285cb0","description":"<p>Load available discos and limits, verify the meter and meter type, then purchase. Query the order for completion and any prepaid token.</p>\n","_postman_id":"ff8e412d-adf4-415f-a3d0-59d0a4285cb0","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Betting","item":[{"name":"Betting providers","id":"1392c708-d788-4f03-ad4e-d6ac8f4827de","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/betting/providers","description":"<p>Read <code>BETTING_COMPANY[]</code>. Send the selected <code>PRODUCT_CODE</code> as <code>BettingCompany</code>; use current limits returned with the provider.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["betting","providers"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"350d1aaf-7a9f-4d4b-8b50-de7cfa7d2854","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/betting/providers"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"BETTING_COMPANY\": [\n    {\n      \"PRODUCT_CODE\": \"EXAMPLE_BILLER\",\n      \"PRODUCT_NAME\": \"Example biller\",\n      \"DISCOUNT_AMOUNT\": \"1.0000\",\n      \"DISCOUNT\": \"0.00%\",\n      \"MINAMOUNT\": 100,\n      \"MAXAMOUNT\": 50000\n    }\n  ]\n}"},{"id":"b273679c-50b7-424d-a67b-4a292db2d091","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/betting/providers"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"1392c708-d788-4f03-ad4e-d6ac8f4827de"},{"name":"Fund betting account","id":"a4883c0e-1f6d-4074-a507-638250bf4dc4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","betting"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"dba6b367-1c9e-4b60-8827-97d3963da4e2","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Betting\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"EXAMPLE_CUSTOMER\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"8e149fa1-38f9-422d-84c6-82cbca12e63c","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"f9af00e5-5ba4-4c13-8067-8a4588c1aa46","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"dabca3de-4368-4a00-83ba-b075fccf3448","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Betting\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"EXAMPLE_CUSTOMER\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"79ec2c5b-295d-408c-babf-7be7ad04e23f","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\",\n  \"Amount\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/betting"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"a4883c0e-1f6d-4074-a507-638250bf4dc4"},{"name":"Verify betting customer","id":"7c0b9d44-37b8-4a98-a0b1-4bd4b605ad3e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting","description":"<p>Read-only provider verification. No purchase is made.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["verify","betting"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"ef10d84c-10cb-40e9-a2d6-1ad051b635b1","name":"Illustrative success","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFIED\",\n  \"valid\": true,\n  \"customer_name\": \"Example customer\",\n  \"validation_reference\": \"\"\n}"},{"id":"5bdaa8d0-7a15-4ff8-aa98-eff7a7d12633","name":"VERIFICATION_REJECTED","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFICATION_REJECTED\",\n  \"message\": \"verification rejected\",\n  \"valid\": false\n}"},{"id":"c7a96e93-d9b2-4380-9b97-b3f458aaa12f","name":"INVALID_PROVIDER_RESPONSE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting"},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"INVALID_PROVIDER_RESPONSE\",\n  \"message\": \"invalid provider response\"\n}"},{"id":"59ae3203-b701-4628-aedb-814c6aac681c","name":"PROVIDER_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_UNAVAILABLE\",\n  \"message\": \"provider unavailable\"\n}"},{"id":"b01a71f3-485a-4904-ab0b-f44ab2a4493d","name":"PROVIDER_TIMEOUT","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"BettingCompany\": \"\",\n  \"CustomerID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/betting"},"status":"Gateway Timeout","code":504,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_TIMEOUT\",\n  \"message\": \"provider timeout\"\n}"}],"_postman_id":"7c0b9d44-37b8-4a98-a0b1-4bd4b605ad3e"}],"id":"8017421a-8306-4df0-9fdb-f4be3858d538","description":"<p>Load biller codes, verify the customer ID and then fund that betting account. Verification alone is not a funding request.</p>\n","_postman_id":"8017421a-8306-4df0-9fdb-f4be3858d538","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Recharge e-PINs","item":[{"name":"Get e-PIN networks and discounts","id":"8723d777-bb3d-46f8-abea-15548b94f752","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/epin/networks","description":"<p><strong>Pending deployment.</strong> The new e-PIN catalogue routes are documented ahead of release. Until deployment, use <code>GET /v1/epin/discounts</code> for network discounts.</p>\n<p>List e-PIN networks and the recharge-card discount for each network. Use NETWORK_ID as MobileNetwork when requesting values or placing an order.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["epin","networks"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"56e01f40-481b-4c4d-82ce-6b7d9b2b7b7e","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/epin/networks"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"MOBILE_NETWORK\": [\n    {\n      \"NETWORK_NAME\": \"MTN\",\n      \"NETWORK_ID\": \"01\",\n      \"DISCOUNT_AMOUNT\": \"1.000\",\n      \"DISCOUNT\": \"0%\"\n    }\n  ]\n}"},{"id":"643a50f7-b868-4a18-9f4a-ac61af103c7e","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/epin/networks"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"8723d777-bb3d-46f8-abea-15548b94f752"},{"name":"Get e-PIN values and available quantities","id":"34545075-d437-4a5f-990e-5f108b2de78f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/epin/values","description":"<p><strong>Pending deployment.</strong> The new e-PIN catalogue routes are documented ahead of release. Until deployment, use <code>GET /v1/epin/discounts</code> for network discounts.</p>\n<p>List recharge PIN face values and available quantities. Omit MobileNetwork for all networks or pass a network ID such as 01. A zero quantity means sold out. Checkout rechecks availability; each order accepts up to 100 PINs.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["epin","values"],"host":["https://api.nellobytesystems.com/v1"],"query":[{"disabled":true,"description":{"content":"<p>Optional network ID. Omit for all networks.</p>\n","type":"text/plain"},"key":"MobileNetwork","value":"01"}],"variable":[]}},"response":[{"id":"380401a6-a4ac-4137-8386-3d32823f23ee","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/epin/values","host":["https://api.nellobytesystems.com/v1"],"path":["epin","values"],"query":[{"key":"MobileNetwork","value":"01","description":"Optional network ID. Omit for all networks.","disabled":true}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"networks\": [\n    {\n      \"MobileNetwork\": \"01\",\n      \"name\": \"MTN\",\n      \"values\": [\n        {\n          \"Value\": \"100\",\n          \"quantity_available\": 240\n        },\n        {\n          \"Value\": \"200\",\n          \"quantity_available\": 35\n        },\n        {\n          \"Value\": \"500\",\n          \"quantity_available\": 0\n        },\n        {\n          \"Value\": \"1000\",\n          \"quantity_available\": 10\n        }\n      ]\n    }\n  ]\n}"},{"id":"ad43495e-b1f4-4799-a49d-7e5c201201b5","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":{"raw":"https://api.nellobytesystems.com/v1/epin/values","host":["https://api.nellobytesystems.com/v1"],"path":["epin","values"],"query":[{"key":"MobileNetwork","value":"01","description":"Optional network ID. Omit for all networks.","disabled":true}]}},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"34545075-d437-4a5f-990e-5f108b2de78f"},{"name":"Generate recharge e-PINs","event":[{"listen":"test","script":{"type":"text/javascript","exec":["// Save the confirmed order ID only. Never repeat or chain a purchase.","if (pm.response.code === 200 || pm.response.code === 202) {","  const order = pm.response.json();","  if (order.orderid) pm.collectionVariables.set(\"orderId\", String(order.orderid));","}"],"id":"ad7043de-ff55-473c-a30a-5d2e1a138531"}}],"id":"5b42419e-7813-4d4b-9af4-58fe4f808bd3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","epin"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"cbe25a65-4c95-4ecb-8677-7f6726cb4fc5","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"EXAMPLE_BATCH\",\n  \"TXN_EPIN\": [\n    {\n      \"transactionid\": \"EXAMPLE_ORDER_ID\",\n      \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n      \"batchno\": \"EXAMPLE_BATCH\",\n      \"mobilenetwork\": \"MTN\",\n      \"sno\": \"EXAMPLE_SERIAL\",\n      \"pin\": \"EXAMPLE_PIN_NOT_VALID\",\n      \"amount\": \"100\"\n    }\n  ],\n  \"detailsstatus\": \"AVAILABLE\",\n  \"ORDER_ID\": \"EXAMPLE_ORDER_ID\"\n}"},{"id":"7d46c697-0bf4-4480-bccb-c75f70824a17","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"eb578383-96b9-4ec6-b2b6-7da3bd76e0e9","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"321f4ec4-fcf2-4e0a-a84c-5e71332e0d33","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"},{"id":"c665dc27-9260-405a-8476-0dac149f7ac0","name":"Accepted e-PIN batch - poll existing order","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"Value\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/epin","description":"Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.\n\nEvery successfully read order has `status`, `orderid`, `transactionid`, `requestid`, `transactiondate`, `producttype`, `productname`, `amount`, `walletbalance`, `paymentoption` and `remark`, plus product-specific details. Empty detail fields are empty strings. `remark` is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. `amount` uses the saved debit where present, and `amountcredited` describes a positive saved credit (not cashback).\n\n| Status | Meaning |\n| --- | --- |\n| ORDER_RECEIVED | Saved Paid state; delivery not yet confirmed. |\n| ORDER_PENDING | Saved Pending state. |\n| ORDER_PROCESSING | Processing, or awaiting the final completion receipt. |\n| ORDER_PROCESSED | Saved Processed state; not equivalent to Completed. |\n| ORDER_COMPLETED | Saved Completed state with no pending completion marker. |\n| ORDER_REFUNDED | Saved Refunded state. |\n| ORDER_CANCELLED | Saved Cancelled state. |\n| ORDER_FAILED | Saved Failed state; this response does not itself refund anything. |\n| ORDER_FINISHED_WITH_FAILURES | All children finished, with mixed completed/refunded/cancelled/failed states. |\n| ORDER_STATUS_UNAVAILABLE | Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response. |\n| ORDER_NOT_FOUND | No owned order was found for the supplied selector. This does not prove no earlier payment occurred. |\n\nAn unavailable post-purchase read retains `orderid`, `requestid`, and `saved: true`. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.\n\nFor a multi-phone airtime request, the top-level status covers the entire request and `orders` contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.\n\ne-PIN orders retain `TXN_EPIN` or `TXN_EPIN_DATABUNDLE` when their complete owned batch is available, together with `ORDER_ID` and `detailsstatus: AVAILABLE`. `detailsstatus: PENDING` or `UNAVAILABLE` does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.\n\nREST response contract (20261102-2)\n\nSuccessful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.\n\nWallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.\n\nErrors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.\n\nIf a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.\n\nWallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.\n\nLimits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.\n\nThe response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.\n\n\nREST purchase protection (contract 20261102-3)\n\nAll ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.\n\nAn identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.\n\nNew successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.\n\nReceipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.\n\nThese protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.\n\n\ne-PIN asynchronous responses (20261103-1)\n\nPOST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.\n\nGET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.\n\nGET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.\n\nPoll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.\n\nFor large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.\n\nepin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.\n"},"status":"Accepted","code":202,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"Location","value":"/v1/orders?OrderID=123&IncludePINs=false"},{"key":"Retry-After","value":"5"},{"key":"X-Rest-EPIN-Async","value":"20261103-1"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_RECEIVED\",\n  \"orderid\": \"123\",\n  \"transactionid\": \"123\",\n  \"requestid\": \"example-epin-001\",\n  \"detailsstatus\": \"PENDING\",\n  \"status_url\": \"/v1/orders?OrderID=123&IncludePINs=false\",\n  \"pins_url\": \"/v1/orders?OrderID=123&IncludePINs=true\",\n  \"retry_after_seconds\": 5\n}"}],"_postman_id":"5b42419e-7813-4d4b-9af4-58fe4f808bd3"}],"id":"0c2944db-f749-468f-86c3-7105d516c336","description":"<p>Read airtime e-PIN discounts and generate an intentional batch. Generated PINs are private and should not be published in examples.</p>\n","_postman_id":"0c2944db-f749-468f-86c3-7105d516c336","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Data e-PINs","item":[{"name":"Generate data e-PINs","event":[{"listen":"test","script":{"type":"text/javascript","exec":["// Save the confirmed order ID only. Never repeat or chain a purchase.","if (pm.response.code === 200 || pm.response.code === 202) {","  const order = pm.response.json();","  if (order.orderid) pm.collectionVariables.set(\"orderId\", String(order.orderid));","}"],"id":"b39ca4fc-033d-4669-826d-ba2927d6c8ba"}}],"id":"e557ae1c-5aa6-4fbb-a956-7a4e8ae19500","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n<p>e-PIN asynchronous responses (20261103-1)</p>\n<p>POST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&amp;IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.</p>\n<p>GET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.</p>\n<p>GET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.</p>\n<p>Poll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.</p>\n<p>For large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.</p>\n<p>epin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","databundle-epin"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"6e9e2060-088f-456c-8d70-6a352fdbd251","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"AirTime\",\n  \"productname\": \"100 Credit\",\n  \"amount\": \"100.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"EXAMPLE_BATCH\",\n  \"TXN_EPIN_DATABUNDLE\": [\n    {\n      \"transactionid\": \"EXAMPLE_ORDER_ID\",\n      \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n      \"batchno\": \"EXAMPLE_BATCH\",\n      \"mobilenetwork\": \"MTN\",\n      \"sno\": \"EXAMPLE_SERIAL\",\n      \"pin\": \"EXAMPLE_PIN_NOT_VALID\",\n      \"productname\": \"500MB - Weekly (SME)\"\n    }\n  ],\n  \"detailsstatus\": \"AVAILABLE\",\n  \"ORDER_ID\": \"EXAMPLE_ORDER_ID\"\n}"},{"id":"6c81d2d7-0897-4800-87ca-fb9f0409e484","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"0bcbeb56-5e07-42e3-8510-8e1332571450","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"d4619bba-3627-4d23-bfff-c3aaebd5eccb","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"},{"id":"b02ea0ba-e369-4134-99de-ea90bf72a7d4","name":"Accepted e-PIN batch - poll existing order","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"\",\n  \"DataPlan\": \"\",\n  \"Quantity\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/databundle-epin","description":"Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.\n\nEvery successfully read order has `status`, `orderid`, `transactionid`, `requestid`, `transactiondate`, `producttype`, `productname`, `amount`, `walletbalance`, `paymentoption` and `remark`, plus product-specific details. Empty detail fields are empty strings. `remark` is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. `amount` uses the saved debit where present, and `amountcredited` describes a positive saved credit (not cashback).\n\n| Status | Meaning |\n| --- | --- |\n| ORDER_RECEIVED | Saved Paid state; delivery not yet confirmed. |\n| ORDER_PENDING | Saved Pending state. |\n| ORDER_PROCESSING | Processing, or awaiting the final completion receipt. |\n| ORDER_PROCESSED | Saved Processed state; not equivalent to Completed. |\n| ORDER_COMPLETED | Saved Completed state with no pending completion marker. |\n| ORDER_REFUNDED | Saved Refunded state. |\n| ORDER_CANCELLED | Saved Cancelled state. |\n| ORDER_FAILED | Saved Failed state; this response does not itself refund anything. |\n| ORDER_FINISHED_WITH_FAILURES | All children finished, with mixed completed/refunded/cancelled/failed states. |\n| ORDER_STATUS_UNAVAILABLE | Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response. |\n| ORDER_NOT_FOUND | No owned order was found for the supplied selector. This does not prove no earlier payment occurred. |\n\nAn unavailable post-purchase read retains `orderid`, `requestid`, and `saved: true`. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.\n\nFor a multi-phone airtime request, the top-level status covers the entire request and `orders` contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.\n\ne-PIN orders retain `TXN_EPIN` or `TXN_EPIN_DATABUNDLE` when their complete owned batch is available, together with `ORDER_ID` and `detailsstatus: AVAILABLE`. `detailsstatus: PENDING` or `UNAVAILABLE` does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.\n\nREST response contract (20261102-2)\n\nSuccessful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.\n\nWallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.\n\nErrors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.\n\nIf a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.\n\nWallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.\n\nLimits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.\n\nThe response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.\n\n\nREST purchase protection (contract 20261102-3)\n\nAll ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.\n\nAn identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.\n\nNew successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.\n\nReceipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.\n\nThese protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.\n\n\ne-PIN asynchronous responses (20261103-1)\n\nPOST /orders/epin and /orders/databundle-epin return HTTP 202 Accepted while a\nconfirmed saved order is waiting for its complete PIN batch. The JSON retains\nthe current saved status, orderid, requestid and wallet snapshots. Location and\nstatus_url point to GET /v1/orders?OrderID=...&IncludePINs=false; Retry-After and\nretry_after_seconds suggest five seconds before the next lookup. A batch already\nready returns HTTP 200 with detailsstatus AVAILABLE and its existing PIN array.\nSaved RequestID replays follow the same rule without another purchase. An\nunconfirmed save is never converted into an accepted order.\n\nGET /orders accepts optional IncludePINs=true|false (default true). Exactly one\nOrderID, RequestID or BatchNo is still required. Both modes require the same\nmember authentication. false returns status and readiness without transferring\nPIN values; true includes the complete owned PIN batch when ready. pins_url\npoints to the full lookup. These links contain no credentials.\n\nGET returns HTTP 200 while the PIN batch is PENDING. AVAILABLE means all requested\nPINs were readable at that observation. An incomplete batch returns PENDING and\nno partial PIN array. A SQL failure, invalid batch or conflicting PIN data returns\nHTTP 503 with UNAVAILABLE, not a generation result. NOT_APPLICABLE means the order\nis failed, cancelled or refunded; stop polling. The saved financial status is\npreserved: ORDER_COMPLETED alone does not guarantee PIN readiness. Check\ndetailsstatus, and require AVAILABLE with the PIN array before delivering PINs.\n\nPoll from your application: start after five seconds, then back off to 10, 20 and\n30 seconds; stop after a bounded number of attempts. A polling timeout is not a\npurchase failure or permission to refund/rebuy. Retain and query the same order\nor RequestID later. Lost POST responses are queried by RequestID. No new job,\nwebhook delivery system or PIN generator is installed by this update. Normal\ngeneration continues independently; lookup latency is not generation time.\nThe current data e-PIN purchase function creates its batch before committing,\nso it normally returns 200 with AVAILABLE. Its generation is not moved to a\nbackground worker here; the shared reader handles any later pending observation.\n\nFor large batches, use IncludePINs=false until AVAILABLE, then retrieve the PINs\nonce with IncludePINs=true. PIN retrieval is still a full batch, not pagination.\nCounts are bounded at 10,001 rows for the existing 10,000-PIN maximum; this reduces\npayloads but is not a guarantee of zero database load or blocking.\n\nepin-polling.mjs is a server-side integration example using authenticated GETs\nonly, with bounded polling and 30-second per-request timeouts. Import waitForEpin\nand pass orderId, memberId and apiKey from your secure server configuration.\nIt never submits a purchase; store the returned PINs securely and do not log them.\nIt uses the fixed API origin and rejects redirects. Do not embed a member API key\nin public browser code. No automatic collection runner or purchase retry is added.\n"},"status":"Accepted","code":202,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"},{"key":"Location","value":"/v1/orders?OrderID=123&IncludePINs=false"},{"key":"Retry-After","value":"5"},{"key":"X-Rest-EPIN-Async","value":"20261103-1"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_RECEIVED\",\n  \"orderid\": \"123\",\n  \"transactionid\": \"123\",\n  \"requestid\": \"example-epin-001\",\n  \"detailsstatus\": \"PENDING\",\n  \"status_url\": \"/v1/orders?OrderID=123&IncludePINs=false\",\n  \"pins_url\": \"/v1/orders?OrderID=123&IncludePINs=true\",\n  \"retry_after_seconds\": 5\n}"}],"_postman_id":"e557ae1c-5aa6-4fbb-a956-7a4e8ae19500"}],"id":"2b015dcb-1499-410c-8ffc-4a477a80efa5","description":"<p>Use Mobile data / Data plans for PRODUCT_CODE and network ID, then generate the requested quantity. Store returned PINs privately.</p>\n","_postman_id":"2b015dcb-1499-410c-8ffc-4a477a80efa5","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"Smile","item":[{"name":"Smile packages","id":"e856e744-d49d-4b5b-b561-eec899f59ba3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/smile/packages","description":"<p>Read <code>MOBILE_NETWORK[\"smile-direct\"][].PRODUCT[]</code>. Use <code>ID</code> as <code>MobileNetwork</code> and <code>PACKAGE_ID</code> as <code>DataPlan</code>. This is separate from mobile-data PRODUCT_CODE.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["smile","packages"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"2be3cb25-5e47-4a45-a953-3de8aefbff33","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/smile/packages"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"MOBILE_NETWORK\": {\n    \"smile-direct\": [\n      {\n        \"ID\": \"smile-direct\",\n        \"PRODUCT\": [\n          {\n            \"PACKAGE_ID\": \"EXAMPLE_PACKAGE\",\n            \"PACKAGE_NAME\": \"Example package\",\n            \"PACKAGE_AMOUNT\": \"5000\",\n            \"PRODUCT_DISCOUNT_AMOUNT\": \"5000\",\n            \"PRODUCT_DISCOUNT\": \"0\"\n          }\n        ]\n      }\n    ]\n  }\n}"},{"id":"8c5b3b9d-ed18-4116-abb4-8e3c2cd6b96c","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/smile/packages"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"e856e744-d49d-4b5b-b561-eec899f59ba3"},{"name":"Buy Smile package","id":"fad21810-28a8-4b8b-a194-ecf218f9d97c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","smile"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"e671c17a-71c6-41fc-80c1-0ad0e530c4e6","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Smile\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_SMILE_ACCOUNT\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"cc353e41-1ba6-4d84-b563-8be4dda8eb77","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"3279ff2d-1564-47a3-8077-78821d3d4070","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"5fd22513-d5fa-4863-828e-9c2fba8d70d1","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"Smile\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"MTN\",\n  \"mobilenumber\": \"EXAMPLE_SMILE_ACCOUNT\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"3a72a7b2-b967-4e18-be53-e4bfd9735004","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"DataPlan\": \"\",\n  \"MobileNumber\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/smile"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"fad21810-28a8-4b8b-a194-ecf218f9d97c"},{"name":"Verify Smile account","id":"8c956bf2-b390-4432-be5c-331f969e5bec","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile","description":"<p>Read-only provider verification. No purchase is made.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["verify","smile"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"b67aa4bb-c30f-400b-a0a5-ef50f2a8fb8d","name":"Illustrative success","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFIED\",\n  \"valid\": true,\n  \"customer_name\": \"Example customer\",\n  \"validation_reference\": \"\"\n}"},{"id":"1efdc83f-77c2-4d2f-a371-ee0ce3676e62","name":"VERIFICATION_REJECTED","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFICATION_REJECTED\",\n  \"message\": \"verification rejected\",\n  \"valid\": false\n}"},{"id":"05b29d69-d29c-413b-999c-a1f532f05c05","name":"INVALID_PROVIDER_RESPONSE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile"},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"INVALID_PROVIDER_RESPONSE\",\n  \"message\": \"invalid provider response\"\n}"},{"id":"7ebf811f-ce58-46d2-a7b6-effaa820c110","name":"PROVIDER_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_UNAVAILABLE\",\n  \"message\": \"provider unavailable\"\n}"},{"id":"305984f8-93b8-488b-bab4-0d72f0ff8049","name":"PROVIDER_TIMEOUT","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"MobileNetwork\": \"smile-direct\",\n  \"MobileNumber\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/smile"},"status":"Gateway Timeout","code":504,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_TIMEOUT\",\n  \"message\": \"provider timeout\"\n}"}],"_postman_id":"8c956bf2-b390-4432-be5c-331f969e5bec"}],"id":"d1b35ad2-9ad7-4fa0-a5de-9f26a4135786","description":"<p>Use the Smile package catalogue, verify the Smile account and place an order. MobileNumber here is the Smile account identifier.</p>\n","_postman_id":"d1b35ad2-9ad7-4fa0-a5de-9f26a4135786","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"WAEC","item":[{"name":"WAEC packages","id":"f633d696-07c5-40c6-ab1c-bf2cd73a9da4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/waec/packages","description":"<p>Read <code>EXAM_TYPE[]</code>. Use <code>PRODUCT_CODE</code> as <code>ExamType</code>; <code>PRODUCT_DESCRIPTION</code> and <code>PRODUCT_AMOUNT</code> describe the current product.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["waec","packages"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"709544f6-cb51-4ee9-a8a6-2bd2b13d5fcf","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/waec/packages"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"EXAM_TYPE\": [\n    {\n      \"PRODUCT_CODE\": \"EXAMPLE_EXAM\",\n      \"PRODUCT_DESCRIPTION\": \"Example examination product\",\n      \"PRODUCT_AMOUNT\": \"5000\"\n    }\n  ]\n}"},{"id":"8366a58c-8cda-4c9e-9cab-4d618000b0de","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/waec/packages"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"f633d696-07c5-40c6-ab1c-bf2cd73a9da4"},{"name":"Buy WAEC product","id":"005bf872-0ff8-4ebe-a5e3-d755470b59e5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","waec"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"7777b88d-1b66-45a3-aeaa-ac04e5da612d","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"WAEC\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"EXAMPLE_DETAILS_NOT_VALID\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"49b23a2e-0c27-4a93-9209-a1f919e7a3b7","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"96656102-4652-4998-b1b9-74d5b295410d","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"2b3298cb-76a8-4ace-8fd9-48844cfd7ee8","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"WAEC\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"\",\n  \"batchno\": \"\"\n}"},{"id":"a0bba0bb-fa31-4b62-bf45-acb6f2fe4f80","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/waec"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"005bf872-0ff8-4ebe-a5e3-d755470b59e5"}],"id":"5c0ffc0f-90a3-4334-8ce0-877be0f4d35f","description":"<p>Load current examination products and select PRODUCT_CODE as ExamType before ordering.</p>\n","_postman_id":"5c0ffc0f-90a3-4334-8ce0-877be0f4d35f","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}},{"name":"JAMB","item":[{"name":"JAMB packages","id":"3d5c8cbe-7c6c-48aa-8b89-8e8af7768779","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/jamb/packages","description":"<p>Read <code>EXAM_TYPE[]</code>. Use <code>PRODUCT_CODE</code> as <code>ExamType</code>; do not hard-code a previous examination product or price.</p>\n<p><strong>Authentication:</strong> Collection Bearer Token (<code>apiKey</code>) plus the <code>X-User-ID: </code> header.</p>\n<p><strong>Parameters:</strong> None. Do not add query parameters or a request body.</p>\n<p>Saved response examples are <strong>illustrative</strong>, not live responses or current prices.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["jamb","packages"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"fdafb06c-294b-4456-9eaa-cc9b407b0052","name":"Illustrative success response","originalRequest":{"method":"GET","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/jamb/packages"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"EXAM_TYPE\": [\n    {\n      \"PRODUCT_CODE\": \"EXAMPLE_EXAM\",\n      \"PRODUCT_DESCRIPTION\": \"Example examination product\",\n      \"PRODUCT_AMOUNT\": \"5000\"\n    }\n  ]\n}"},{"id":"0959bf88-62d3-4f59-95f1-47734937933e","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"GET","header":[{"key":"Accept","value":"application/json"}],"url":"https://api.nellobytesystems.com/v1/jamb/packages"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"}],"_postman_id":"3d5c8cbe-7c6c-48aa-8b89-8e8af7768779"},{"name":"Buy JAMB product","id":"17a36610-9ac7-4260-a507-bc4b392806ce","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb","description":"<p>Purchase responses and GET /orders use the same current saved-status reader. Status is observed after the financial operation commits; the API does not wait for delivery or send another purchase. A response may already be ORDER_COMPLETED, or remain ORDER_RECEIVED / ORDER_PROCESSING. Poll GET /orders with the same OrderID or RequestID to observe later progress.</p>\n<p>Every successfully read order has <code>status</code>, <code>orderid</code>, <code>transactionid</code>, <code>requestid</code>, <code>transactiondate</code>, <code>producttype</code>, <code>productname</code>, <code>amount</code>, <code>walletbalance</code>, <code>paymentoption</code> and <code>remark</code>, plus product-specific details. Empty detail fields are empty strings. <code>remark</code> is the actual saved operator/admin comment, JSON escaped; a generic success message is not substituted. An explicit pending completion receipt keeps status ORDER_PROCESSING and withholds staged final remarks/tokens until completion is saved. Dates are ISO 8601 with the database server UTC offset; amount and walletbalance are decimal strings without grouping commas. <code>amount</code> uses the saved debit where present, and <code>amountcredited</code> describes a positive saved credit (not cashback).</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ORDER_RECEIVED</td>\n<td>Saved Paid state; delivery not yet confirmed.</td>\n</tr>\n<tr>\n<td>ORDER_PENDING</td>\n<td>Saved Pending state.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSING</td>\n<td>Processing, or awaiting the final completion receipt.</td>\n</tr>\n<tr>\n<td>ORDER_PROCESSED</td>\n<td>Saved Processed state; not equivalent to Completed.</td>\n</tr>\n<tr>\n<td>ORDER_COMPLETED</td>\n<td>Saved Completed state with no pending completion marker.</td>\n</tr>\n<tr>\n<td>ORDER_REFUNDED</td>\n<td>Saved Refunded state.</td>\n</tr>\n<tr>\n<td>ORDER_CANCELLED</td>\n<td>Saved Cancelled state.</td>\n</tr>\n<tr>\n<td>ORDER_FAILED</td>\n<td>Saved Failed state; this response does not itself refund anything.</td>\n</tr>\n<tr>\n<td>ORDER_FINISHED_WITH_FAILURES</td>\n<td>All children finished, with mixed completed/refunded/cancelled/failed states.</td>\n</tr>\n<tr>\n<td>ORDER_STATUS_UNAVAILABLE</td>\n<td>Status could not be confirmed; retain the reference and query again. Never infer failure or resubmit a purchase from this response.</td>\n</tr>\n<tr>\n<td>ORDER_NOT_FOUND</td>\n<td>No owned order was found for the supplied selector. This does not prove no earlier payment occurred.</td>\n</tr>\n</tbody>\n</table>\n</div><p>An unavailable post-purchase read retains <code>orderid</code>, <code>requestid</code>, and <code>saved: true</code>. HTTP 200 alone does not establish completion. Read failures use HTTP 503; missing owned orders use HTTP 404. Other errors use the REST error contract.</p>\n<p>For a multi-phone airtime request, the top-level status covers the entire request and <code>orders</code> contains each child's receipt. Missing or ambiguous source records produce ORDER_STATUS_UNAVAILABLE. For operational orders, GET by a child's order ID returns the request group when its request metadata is available.</p>\n<p>e-PIN orders retain <code>TXN_EPIN</code> or <code>TXN_EPIN_DATABUNDLE</code> when their complete owned batch is available, together with <code>ORDER_ID</code> and <code>detailsstatus: AVAILABLE</code>. <code>detailsstatus: PENDING</code> or <code>UNAVAILABLE</code> does not change the financial status or authorize another purchase. Retry the existing order lookup for unavailable PIN details. No provider requery, vend, callback, refund or wallet update is performed by this status reader.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n<p>REST purchase protection (contract 20261102-3)</p>\n<p>All ten purchase routes retain a durable request receipt keyed by the authenticated\nmember and RequestID. Keep the same route and field values for an identical retry.\nJSON property order and property-name casing do not affect identity. Missing and\nempty optional fields are equivalent; different supplied field values (including\nnumeric spellings, Memo and callback URL) are conservatively treated as a conflict.\nThe database stores a SHA-256 fingerprint, not the raw request or API key.</p>\n<p>An identical saved request returns its CURRENT operational order status without\nanother purchase. Idempotent-Replayed: true identifies a replay. Changed details\nor another product with the same member/RequestID return HTTP 409 REQUEST_ID_CONFLICT.\nA request still processing, interrupted, or with uncertain save outcome returns\nHTTP 409 REQUEST_OUTCOME_PENDING_REVIEW. Query GET /orders using RequestID or\ncontact support; do not replace the RequestID to work around that response.\nRequests rejected before purchase SQL retain their rejection. Corrected purchases\nuse a new RequestID only once the previous rejection is definite.</p>\n<p>New successful purchase/RequestID responses include wallet_before and wallet_after,\ndecimal strings describing the saved request's wallet snapshots. They are captured\ninside the purchase transaction and exposed only after commit, including batches.\nThey describe the original purchase, not the customer's current wallet after later\nactivity or a refund. GET /wallet remains the current wallet observation.\nFor an older airtime request adopted by its existing replay mechanism, unavailable\nhistorical wallet snapshots are empty rather than invented.</p>\n<p>Receipt and source-item writes commit with the debit/order. If the order fails,\nthose writes roll back while the initial pending claim is retained for review.\nThere is no automatic claim expiry or repeat purchase after an ambiguous failure.\nAn old receipt cannot be reused just because its operational record is no longer available:\nthe receipt persists, and unavailable current status returns 503 with saved=true.\nRetained display details cannot authorize financial operations.</p>\n<p>These protections cover REST requests first submitted after deployment. Prior\nunconfirmed requests and legacy endpoints are not backfilled into this ledger.\nDo not re-submit a pre-deployment uncertain request; reconcile its saved payment.\nExisting pricing, cashback, delivery mapping and legacy endpoints stay unchanged.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["orders","jamb"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"93ef6b2b-3c3f-4e50-b028-b03f75ba068f","name":"Illustrative current saved completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_COMPLETED\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"JAMB\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"Example saved operator completion message.\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"EXAMPLE_DETAILS_NOT_VALID\",\n  \"profileid\": \"EXAMPLE_PROFILE\",\n  \"batchno\": \"\"\n}"},{"id":"5fb3616c-4e65-4649-8c8c-a75e97cb6ad4","name":"Missing authentication headers","originalRequest":{"auth":{"type":"noauth"},"method":"POST","header":[{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_CREDENTIALS\",\n  \"message\": \"missing credentials\"\n}"},{"id":"a99a0a9d-4927-4d7a-8418-c234fbd7e97a","name":"Missing RequestID (rejected before purchase)","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"MISSING_REQUESTID\",\n  \"message\": \"missing requestid\"\n}"},{"id":"87f5dd83-5853-4620-9624-304c3be9c3b9","name":"Illustrative current pending completion","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_PROCESSING\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"transactionid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"transactiondate\": \"2026-11-02T12:00:00+01:00\",\n  \"producttype\": \"JAMB\",\n  \"productname\": \"Example product\",\n  \"amount\": \"5000.00\",\n  \"amountcredited\": \"\",\n  \"walletbalance\": \"1000.00\",\n  \"paymentoption\": \"Wallet\",\n  \"remark\": \"\",\n  \"mobilenetwork\": \"\",\n  \"mobilenumber\": \"EXAMPLE_PHONE\",\n  \"smartcardno\": \"\",\n  \"meterno\": \"\",\n  \"metertoken\": \"\",\n  \"customerid\": \"\",\n  \"carddetails\": \"\",\n  \"profileid\": \"EXAMPLE_PROFILE\",\n  \"batchno\": \"\"\n}"},{"id":"dd3d6b21-da45-487c-845b-f6c26caf2fd4","name":"Current status unavailable - query existing reference","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\",\n  \"PhoneNo\": \"\",\n  \"RequestID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/orders/jamb"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"ORDER_STATUS_UNAVAILABLE\",\n  \"orderid\": \"EXAMPLE_ORDER_ID\",\n  \"requestid\": \"example-order-001\",\n  \"saved\": true,\n  \"message\": \"Current status could not be read. Query this order or RequestID again; do not submit another purchase.\"\n}"}],"_postman_id":"17a36610-9ac7-4260-a507-bc4b392806ce"},{"name":"Verify JAMB profile","id":"47bb98e5-e72e-483b-ab78-de89f14b7a62","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"<p>Required member ID corresponding to the Bearer API key.</p>\n"},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb","description":"<p>Read-only provider verification. No purchase is made.</p>\n<p>REST response contract (20261102-2)</p>\n<p>Successful business responses use HTTP 200. Always inspect the JSON status: a saved\npurchase may still be ORDER_RECEIVED, ORDER_PENDING or ORDER_PROCESSING. Only a\nsaved completion returns ORDER_COMPLETED. Purchase and order lookups use the same\noperational status reader; no provider purchase is retried by response formatting.</p>\n<p>Wallet: status=WALLET_SUCCESS, id, phoneno, balance, currency=NGN, date.\nVerification: status=VERIFIED, valid=true, customer_name, validation_reference.\nAn optional customer name/reference can be empty when the provider explicitly\nconfirms that no validation reference is required. Verification does not vend.</p>\n<p>Errors use a non-200 HTTP status and JSON status/message:\n400 malformed request; 401 missing or invalid credentials; 403 blocked account,\nIP restriction, HTTPS or KYC requirement; 404 owned order not found;\n405 unsupported method; 413 oversized body; 415 unsupported content type;\n422 invalid input, business rejection, or VERIFICATION_REJECTED with valid=false;\n429 rate limit with Retry-After: 1; 502 malformed provider response;\n503 dependency or saved-state unavailable; 504 provider verification timeout.\nAn outage is not reported as an invalid customer. Raw provider error bodies and\ncredentials are not returned. Clients should retain RequestID before sending.</p>\n<p>If a purchase was attempted but its result cannot be confirmed, the error retains\nrequestid, outcome=UNKNOWN, orderid when available, and next_action. An unavailable\npost-purchase status read returns ORDER_STATUS_UNAVAILABLE with saved=true when\nthe save was confirmed. Query the same reference before another purchase. Never\nautomatically submit a purchase again because a response is 5xx or a lookup is 404.\nORDER_NOT_FOUND describes an unsuccessful order lookup; it is not proof that no purchase occurred. PIN detail availability is separate from status.</p>\n<p>Wallet and current-order money fields are decimal strings with two decimal places\nand no grouping commas. Dates are ISO 8601 with the database server's UTC offset,\nfor example 2026-11-02T12:00:00+01:00. Catalogue schemas and prices are unchanged.\nCable TV uses the submitted MobileNumber; betting uses submitted PhoneNo when\npresent, otherwise the authenticated member's phone. These phone fields accept\nlocal 0-prefixed and +234/234 formats. Accepted Memo is passed to purchase storage.</p>\n<p>Limits are shared across each category per source IP, per IIS worker: 30 purchase\nrequests/second, 10 verification requests/second, 60 authenticated-route GET\nrequests/second. Invalid credentials also consume the category limit. Health,\nOPTIONS, documentation and private helper calls are excluded. Counters are bounded\nin memory and reset on application recycle; this is not a distributed account\nquota. A full counter bucket also returns 429 until the next second.</p>\n<p>The response header X-Rest-Contract: 20261102-2 identifies this deployment.\nExisting REST route names, request fields, standard key authentication, financial\nfunctions, delivery mapping, commission and database procedures are retained.\nThis response contract applies only to api.nellobytesystems.com/v1.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}},"urlObject":{"path":["verify","jamb"],"host":["https://api.nellobytesystems.com/v1"],"query":[],"variable":[]}},"response":[{"id":"324fcf0a-c406-4120-8ed5-6711a4f86a13","name":"Illustrative success","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFIED\",\n  \"valid\": true,\n  \"customer_name\": \"Example customer\",\n  \"validation_reference\": \"\"\n}"},{"id":"fe186c9e-2a71-4a77-a7a6-ab19f07552ee","name":"VERIFICATION_REJECTED","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb"},"status":"Unprocessable Entity","code":422,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"VERIFICATION_REJECTED\",\n  \"message\": \"verification rejected\",\n  \"valid\": false\n}"},{"id":"388e827f-183c-4cac-90f3-c68f6716043e","name":"INVALID_PROVIDER_RESPONSE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb"},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"INVALID_PROVIDER_RESPONSE\",\n  \"message\": \"invalid provider response\"\n}"},{"id":"1aa6d520-c46f-49e4-9a28-7762040b94b6","name":"PROVIDER_UNAVAILABLE","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb"},"status":"Service Unavailable","code":503,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_UNAVAILABLE\",\n  \"message\": \"provider unavailable\"\n}"},{"id":"5257ab0e-5a7d-4814-aaf9-f700422600ab","name":"PROVIDER_TIMEOUT","originalRequest":{"method":"POST","header":[{"key":"X-User-ID","value":"","description":"Required member ID corresponding to the Bearer API key."},{"key":"Accept","value":"application/json"},{"key":"Content-Type","value":"application/json"}],"body":{"mode":"raw","raw":"{\n  \"ExamType\": \"\",\n  \"ProfileID\": \"\"\n}","options":{"raw":{"language":"json"}}},"url":"https://api.nellobytesystems.com/v1/verify/jamb"},"status":"Gateway Timeout","code":504,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json; charset=utf-8"}],"cookie":[],"responseTime":null,"body":"{\n  \"status\": \"PROVIDER_TIMEOUT\",\n  \"message\": \"provider timeout\"\n}"}],"_postman_id":"47bb98e5-e72e-483b-ab78-de89f14b7a62"}],"id":"36cac83d-8589-4ea5-a399-29f4f3fae802","description":"<p>Load current examination products, verify the profile and select PRODUCT_CODE as ExamType before ordering.</p>\n","_postman_id":"36cac83d-8589-4ea5-a399-29f4f3fae802","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","id":"5e6673d7-0a01-4c5c-8978-c9ec295509ab","name":"Nellobyte REST API v1","type":"collection"}}}],"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]}},"variable":[{"key":"baseUrl","value":"https://api.nellobytesystems.com/v1","description":"Production HTTPS base URL without a trailing slash."},{"key":"memberId","value":"","description":"Set your member ID locally. Keep the shared value blank."},{"key":"apiKey","value":"","description":"Set the member standard API key locally or use Postman Vault. Never share or publish it."},{"key":"requestId","value":"","description":"Choose once per intended purchase; retain for query/reconciliation. No automatic regeneration."},{"key":"orderId","value":"","description":"Copy the original order identifier after purchase."},{"key":"batchNo","value":"","description":"Copy a saved PIN batch reference."},{"key":"mobileNetwork","value":"","description":"NETWORK_ID from the airtime/data catalogue, such as 01."},{"key":"mobileNumber","value":"","description":"Destination phone number; keep leading zeroes."},{"key":"phoneNo","value":"","description":"Contact phone number; keep leading zeroes."},{"key":"amount","value":"","description":"Intended monetary amount in naira without commas."},{"key":"dataPlanCode","value":"","description":"Current PRODUCT_CODE from the chosen data network."},{"key":"cableTv","value":"","description":"TV_ID from Cable TV providers."},{"key":"cablePackage","value":"","description":"PACKAGE_ID for the chosen cable provider."},{"key":"smartCardNo","value":"","description":"Verified smart-card/IUC number."},{"key":"electricCompany","value":"","description":"Current company ID from Electricity discos."},{"key":"meterNo","value":"","description":"Verified meter number."},{"key":"meterType","value":"","description":"prepaid or postpaid, matching verification."},{"key":"bettingCompany","value":"","description":"PRODUCT_CODE from Betting providers."},{"key":"customerId","value":"","description":"Verified betting customer identifier."},{"key":"epinValue","value":"","description":"Requested airtime recharge-card denomination."},{"key":"quantity","value":"","description":"Intentional number of PINs, a positive integer."},{"key":"smileNetwork","value":"smile-direct","description":"Smile network ID from its catalogue."},{"key":"smilePackage","value":"","description":"PACKAGE_ID from Smile packages."},{"key":"smileAccount","value":"","description":"Verified Smile account identifier."},{"key":"waecExamType","value":"","description":"PRODUCT_CODE from WAEC packages."},{"key":"jambExamType","value":"","description":"PRODUCT_CODE from JAMB packages."},{"key":"profileId","value":"","description":"Verified JAMB profile identifier."}]}