{"openapi":"3.1.0","info":{"title":"Neomarket API","version":"1.0.0","description":"Buy verification numbers, boosting and marketplace goods from your Neomarket wallet, and read the catalog for every other Neomarket service. All prices are in NGN and every purchase is debited from a single shared wallet. See https://neomarket.com.ng/api-docs for the full guide.","contact":{"url":"https://neomarket.com.ng/api-docs"}},"servers":[{"url":"https://neomarket.com.ng/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Wallet","description":"Read the shared wallet balance."},{"name":"Marketplace","description":"Browse and buy from the product catalog."},{"name":"Numbers","description":"Buy one-time verification numbers. A number holds its price in escrow rather than charging it: poll the activation until a code lands (charged) or cancel it for the hold back (free)."},{"name":"Boost","description":"Buy social engagement from the SMM panels. Charged upfront, delivered over time: place an order, poll it, and cancel or refill it. Undelivered units are refunded proportionally when an order is cancelled or ends Partial."},{"name":"Checkmark","description":"Browse account-verification listings. Read-only."},{"name":"Subscriptions","description":"Browse and order subscription top-ups. Ordering holds the price in escrow rather than charging it: requests are fulfilled by hand, so poll the request until it completes (charged) or fails (hold released in full)."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API key from the Neomarket Developer console, sent as 'Authorization: Bearer bvg_live_...'. Required on every endpoint, including catalog reads."}}},"paths":{"/balance":{"get":{"tags":["Wallet"],"operationId":"getBalance","summary":"Get wallet balance","description":"Returns the spendable wallet balance for the key's owner. Free to call. Referral commission is held separately and is not included.","responses":{"200":{"description":"Current balance.","content":{"application/json":{"schema":{"type":"object","properties":{"balance":{"type":"number"},"currency":{"type":"string","enum":["NGN"]}},"required":["balance","currency"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/store/products":{"get":{"tags":["Marketplace"],"operationId":"listStoreProducts","summary":"List marketplace products","description":"The marketplace catalog with live stock counts, in NGN with the account's Premium discount already applied. Free to call. Read-only: buying claims a stock unit and is done from the dashboard.","parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string"},"description":"Case-insensitive exact category filter."}],"responses":{"200":{"description":"Catalog with stock.","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"category":{"type":"string"},"image_url":{"type":"string","nullable":true},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]},"stock":{"type":"integer","description":"Unsold units available right now."}}}}},"required":["products"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/store/orders":{"post":{"tags":["Marketplace"],"operationId":"createStoreOrder","summary":"Buy marketplace products","description":"Claims the requested number of stock units, debits the wallet and returns the purchased items in the response. Nothing here calls an external provider, so every failure rolls back fully — a non-2xx means you were not charged. Send an Idempotency-Key so a retry after a timeout replays the same items rather than buying more.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A unique value per purchase — a UUID is ideal. The first request stores its result; repeats replay it with an 'Idempotent-Replay: true' header instead of spending again. Scoped to your account, expires after 24 hours."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"product_id":{"type":"string","description":"An id from /store/products."},"productId":{"type":"string","description":"Accepted alias for product_id."},"quantity":{"type":"integer","minimum":1,"maximum":50,"default":1,"description":"Units to buy. Each unit is a separate item."}},"required":["product_id"]}}}},"responses":{"200":{"description":"Order delivered, with the purchased items.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"product_id":{"type":"string"},"product_name":{"type":"string"},"quantity":{"type":"integer"},"unit_price":{"type":"number"},"price":{"type":"number","description":"Total debited."},"currency":{"type":"string","enum":["NGN"]},"status":{"type":"string","enum":["delivered"]},"items":{"type":"array","description":"The purchased goods. Store these — this is the delivery.","items":{"type":"object","properties":{"id":{"type":"string"},"value":{"type":"string"}}}}},"required":["id","price","currency","items"]}}}},"400":{"description":"Malformed request or unknown product_id.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Insufficient wallet balance. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Not enough stock, or a request with this Idempotency-Key is still in flight. The message says which. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"This Idempotency-Key was already used with a different request body.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The order could not be recorded and was rolled back in full. You were not charged — safe to retry.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/countries":{"get":{"tags":["Numbers"],"operationId":"listVerifyCountries","summary":"List number countries","description":"Countries that have verification numbers available, for use as the 'country' argument to /verify/services. Free to call.","parameters":[{"name":"server","in":"query","required":false,"schema":{"type":"string","enum":["server-1","server-2"]},"description":"Which server to query. Defaults to the primary. Each server carries its own countries, services, stock and prices, so a country sold out on one is often available on the other. An unrecognised value is rejected rather than silently defaulted."}],"responses":{"200":{"description":"Available countries.","content":{"application/json":{"schema":{"type":"object","properties":{"countries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"has_services":{"type":"boolean"},"operators":{"type":"array","items":{"type":"string"}}}}}},"required":["countries"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/services":{"get":{"tags":["Numbers"],"operationId":"listVerifyServices","summary":"List number services and prices","description":"Services available in a country with live stock counts and NGN prices including the account's Premium discount. Free to call. Pass a 'code' from here as 'service' when buying a number. The price here is INDICATIVE — it comes from the upstream's aggregate catalog and is typically a little above what you actually pay, because buying takes the cheapest operator. For the exact figure, read /verify/servers, whose cheapest option is the price a purchase will be held at.","parameters":[{"name":"country","in":"query","required":true,"schema":{"type":"string"},"description":"A country id from /verify/countries."},{"name":"operators","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated operator filter, or 'any'."},{"name":"server","in":"query","required":false,"schema":{"type":"string","enum":["server-1","server-2"]},"description":"Which server to query. Defaults to the primary. Each server carries its own countries, services, stock and prices, so a country sold out on one is often available on the other. An unrecognised value is rejected rather than silently defaulted."}],"responses":{"200":{"description":"Services on sale.","content":{"application/json":{"schema":{"type":"object","properties":{"services":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"count":{"type":"integer","description":"Numbers in stock, when the upstream reports it."},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]}}}}},"required":["services"]}}}},"400":{"description":"Missing 'country'.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/servers":{"get":{"tags":["Numbers"],"operationId":"listVerifyServers","summary":"List operator options for a service","description":"Per-option prices for a country + service, cheapest first, so you can pick before buying. Pass an 'operator' value straight back as 'operators' on POST /verify/activations. Free to call.","parameters":[{"name":"country","in":"query","required":true,"schema":{"type":"string"},"description":"A country id from /verify/countries."},{"name":"service","in":"query","required":true,"schema":{"type":"string"},"description":"A service code from /verify/services."},{"name":"server","in":"query","required":false,"schema":{"type":"string","enum":["server-1","server-2"]},"description":"Which server to query. Defaults to the primary. Each server carries its own countries, services, stock and prices, so a country sold out on one is often available on the other. An unrecognised value is rejected rather than silently defaulted."}],"responses":{"200":{"description":"Options on sale.","content":{"application/json":{"schema":{"type":"object","properties":{"servers":{"type":"array","items":{"type":"object","properties":{"operator":{"type":"string"},"label":{"type":"string"},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]},"count":{"type":"integer"}}}}},"required":["servers"]}}}},"400":{"description":"Missing 'country' or 'service'.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/activations":{"post":{"tags":["Numbers"],"operationId":"buyVerifyNumber","summary":"Buy a one-time number","description":"Buys a number and holds its price in escrow — you are NOT charged yet. Poll GET /verify/activations/{id} until 'status' becomes 'received' (the hold settles into a real charge and 'otp_code'/'sms_text' are filled in) or the window lapses. Give up early with POST /verify/activations/{id}/cancel and the whole hold comes straight back. This is a three-call flow by design: buy, poll, then either read the code or cancel.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A unique value per purchase — a UUID is ideal. The first request stores its result; repeats replay it with an 'Idempotent-Replay: true' header instead of spending again. Scoped to your account, expires after 24 hours."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"service":{"type":"string","description":"A service code from /verify/services."},"country":{"type":"string","description":"A country id from /verify/countries."},"operators":{"oneOf":[{"type":"array","items":{"type":"string"}},{"type":"string"}],"description":"Preferred operator(s) from /verify/servers, as an array or a comma-separated string. Omit to take the cheapest."},"server":{"type":"string","enum":["server-1","server-2"],"description":"Which server to buy from. Defaults to the primary. Each server carries its own countries, services, stock and prices."},"service_name":{"type":"string","description":"Optional label stored with the order."},"country_name":{"type":"string","description":"Optional label stored with the order."}},"required":["service","country"]}}}},"responses":{"200":{"description":"Number issued, price held in escrow. Nothing has been charged yet.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll and cancel calls."},"status":{"type":"string","enum":["waiting","received","cancelled","expired"],"description":"'waiting' — the hold is open and no code has arrived. 'received' — a code (or an SMS body) landed and the wallet was charged. 'cancelled'/'expired' — the hold was released in full."},"phone_number":{"type":"string"},"service":{"type":"string"},"service_name":{"type":["string","null"]},"country":{"type":"string"},"country_name":{"type":["string","null"]},"server":{"type":"string","enum":["server-1","server-2"],"description":"Which server the number came from."},"price":{"type":"number","description":"NGN held in escrow. Only debited for real once status is 'received'."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True once the hold has settled into an actual wallet charge."},"otp_code":{"type":["string","null"],"description":"The parsed verification code, when one could be extracted."},"sms_text":{"type":["string","null"],"description":"The full SMS body. Some messages carry no parseable code — this is still a delivery and is still charged."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the number stops accepting SMS and the hold is released."},"created_at":{"type":"string","format":"date-time"},"resends":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","received","expired"]},"price":{"type":"number"},"charged":{"type":"boolean"},"otp_code":{"type":["string","null"]},"sms_text":{"type":["string","null"]},"expires_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"description":"Paid re-requests on this number, oldest first."},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","phone_number","price","currency","charged"]}}}},"400":{"description":"Malformed request or failed validation.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Insufficient wallet balance. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"A request with this Idempotency-Key is still in flight. Retry the same key shortly to read its result.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"This Idempotency-Key was already used with a different request body. Use a new key for a new purchase.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The number could not be recorded and was rolled back in full — the hold was released and the number handed back. Nothing was charged; safe to retry with the same Idempotency-Key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"get":{"tags":["Numbers"],"operationId":"listVerifyActivations","summary":"List recent numbers","description":"Your recent numbers, newest first. This is the recovery path when a purchase response is lost on the wire: the number is here, so resume polling it instead of buying another. Free to call.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["waiting","received","cancelled","expired"]},"description":"Return only numbers in this state."}],"responses":{"200":{"description":"Recent numbers.","content":{"application/json":{"schema":{"type":"object","properties":{"activations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll and cancel calls."},"status":{"type":"string","enum":["waiting","received","cancelled","expired"],"description":"'waiting' — the hold is open and no code has arrived. 'received' — a code (or an SMS body) landed and the wallet was charged. 'cancelled'/'expired' — the hold was released in full."},"phone_number":{"type":"string"},"service":{"type":"string"},"service_name":{"type":["string","null"]},"country":{"type":"string"},"country_name":{"type":["string","null"]},"server":{"type":"string","enum":["server-1","server-2"],"description":"Which server the number came from."},"price":{"type":"number","description":"NGN held in escrow. Only debited for real once status is 'received'."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True once the hold has settled into an actual wallet charge."},"otp_code":{"type":["string","null"],"description":"The parsed verification code, when one could be extracted."},"sms_text":{"type":["string","null"],"description":"The full SMS body. Some messages carry no parseable code — this is still a delivery and is still charged."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the number stops accepting SMS and the hold is released."},"created_at":{"type":"string","format":"date-time"},"resends":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","received","expired"]},"price":{"type":"number"},"charged":{"type":"boolean"},"otp_code":{"type":["string","null"]},"sms_text":{"type":["string","null"]},"expires_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"description":"Paid re-requests on this number, oldest first."},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","phone_number","price","currency","charged"]}}},"required":["activations"]}}}},"400":{"description":"Invalid 'limit'.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/activations/{id}":{"get":{"tags":["Numbers"],"operationId":"getVerifyActivation","summary":"Poll a number for its code","description":"Reading a number is what advances it: when a code lands the escrow settles into a real charge, and when the window closes the hold is released. Keep calling while 'poll_after_ms' is non-null. Free to call, but each call counts against the key's rate limit — respect 'poll_after_ms' rather than polling flat out.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the number was bought."}],"responses":{"200":{"description":"Current state of the number.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll and cancel calls."},"status":{"type":"string","enum":["waiting","received","cancelled","expired"],"description":"'waiting' — the hold is open and no code has arrived. 'received' — a code (or an SMS body) landed and the wallet was charged. 'cancelled'/'expired' — the hold was released in full."},"phone_number":{"type":"string"},"service":{"type":"string"},"service_name":{"type":["string","null"]},"country":{"type":"string"},"country_name":{"type":["string","null"]},"server":{"type":"string","enum":["server-1","server-2"],"description":"Which server the number came from."},"price":{"type":"number","description":"NGN held in escrow. Only debited for real once status is 'received'."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True once the hold has settled into an actual wallet charge."},"otp_code":{"type":["string","null"],"description":"The parsed verification code, when one could be extracted."},"sms_text":{"type":["string","null"],"description":"The full SMS body. Some messages carry no parseable code — this is still a delivery and is still charged."},"expires_at":{"type":["string","null"],"format":"date-time","description":"When the number stops accepting SMS and the hold is released."},"created_at":{"type":"string","format":"date-time"},"resends":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["waiting","received","expired"]},"price":{"type":"number"},"charged":{"type":"boolean"},"otp_code":{"type":["string","null"]},"sms_text":{"type":["string","null"]},"expires_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"description":"Paid re-requests on this number, oldest first."},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","phone_number","price","currency","charged"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No number with that id on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/activations/{id}/cancel":{"post":{"tags":["Numbers"],"operationId":"cancelVerifyActivation","summary":"Cancel a waiting number","description":"Hands the number back and releases the whole hold. Because a cancelled number is never charged, 'refunded' here is a released hold and no transaction is written. Only numbers still in 'waiting' can be cancelled — once a code has landed the purchase is settled and final.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the number was bought."}],"responses":{"200":{"description":"Cancelled and released.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["cancelled"]},"refunded":{"type":"number"},"currency":{"type":"string","enum":["NGN"]}},"required":["id","status","refunded"]}}}},"400":{"description":"This number is no longer in 'waiting'.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No number with that id on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/verify/activations/{id}/resend":{"post":{"tags":["Numbers"],"operationId":"resendVerifyActivation","summary":"Request another SMS","description":"Asks the same number for another SMS. Free while the first code is still outstanding ('charged': false — the original hold covers it). Once a code has landed and settled, this is a new purchase at the same price with its own hold and window; poll the activation and watch it resolve under 'resends'. Not every upstream supports this.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the number was bought."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A unique value per purchase — a UUID is ideal. The first request stores its result; repeats replay it with an 'Idempotent-Replay: true' header instead of spending again. Scoped to your account, expires after 24 hours."}],"responses":{"200":{"description":"Another SMS was requested.","content":{"application/json":{"schema":{"type":"object","properties":{"activation_id":{"type":"string"},"charged":{"type":"boolean","description":"False when the original hold already covers this SMS."},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]},"resend_id":{"type":["string","null"]}},"required":["activation_id","charged"]}}}},"400":{"description":"The number is no longer active, or its upstream cannot resend — cancel for the hold back and buy a new one.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Insufficient wallet balance. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No number with that id on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Another SMS is already on the way for this number.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The request could not be started. You were not charged — safe to retry.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/checkmark/listings":{"get":{"tags":["Checkmark"],"operationId":"listCheckmarkListings","summary":"List checkmark listings","description":"Active verification listings in NGN with the account's Premium discount already applied. Free to call. Read-only: requests are fulfilled by hand and credential-type listings take an account password, so ordering stays in the dashboard.","responses":{"200":{"description":"Active listings.","content":{"application/json":{"schema":{"type":"object","properties":{"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"platform":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"image_url":{"type":"string","nullable":true},"verification_type":{"type":"string","enum":["username","credentials"]},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]}}}}},"required":["listings"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/topup/listings":{"get":{"tags":["Subscriptions"],"operationId":"listTopupListings","summary":"List subscription listings","description":"Active subscription and top-up listings in NGN with the account's Premium discount already applied. Free to call. An id from here is what POST /topup/orders is placed against.","responses":{"200":{"description":"Active listings.","content":{"application/json":{"schema":{"type":"object","properties":{"listings":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"platform":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"instructions":{"type":"string","nullable":true,"description":"What the buyer must supply as the account for this listing (player ID, profile link, login email …)."},"image_url":{"type":"string","nullable":true},"price":{"type":"number"},"currency":{"type":"string","enum":["NGN"]}}}}},"required":["listings"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/topup/orders":{"post":{"tags":["Subscriptions"],"operationId":"createTopupOrder","summary":"Order a subscription top-up","description":"Places a subscription request against a listing. Nothing is charged: the discounted listing price is held in escrow and only becomes a real charge once the request is fulfilled — a rejected request hands the whole hold back. Fulfilment is manual, so this returns a 'processing' request, not a finished purchase; poll GET /topup/orders/{id} while poll_after_ms is non-null. Send an Idempotency-Key so a retry after a timeout replays the same request instead of placing a second one.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A unique value per purchase — a UUID is ideal. The first request stores its result; repeats replay it with an 'Idempotent-Replay: true' header instead of spending again. Scoped to your account, expires after 24 hours."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"listing_id":{"type":"string","description":"An id from /topup/listings."},"listingId":{"type":"string","description":"Accepted alias for listing_id."},"account":{"type":"string","description":"The account to top up — email, phone, username or player id. What exactly to send is in the listing's 'instructions' field."},"contact":{"type":"string","description":"Email, phone or WhatsApp we can reach the buyer on if the request needs a question answered."}},"required":["listing_id","account","contact"]}}}},"responses":{"200":{"description":"Request submitted, price held in escrow.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll call."},"status":{"type":"string","enum":["processing","completed","failed"]},"listing_id":{"type":["string","null"]},"platform":{"type":["string","null"]},"title":{"type":["string","null"]},"account":{"type":"string"},"contact":{"type":["string","null"]},"price":{"type":"number","description":"NGN held in escrow."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True only once the request completed. Until then the price is a hold, not a charge."},"notes":{"type":["string","null"],"description":"What the fulfilling admin wrote — typically the reason a request failed."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","price","currency","charged"]}}}},"400":{"description":"Malformed request, missing account/contact, or an unknown or inactive listing_id.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"402":{"description":"Insufficient wallet balance. Nothing was held.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"A request with this Idempotency-Key is still in flight. Retry shortly to read its result.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"This Idempotency-Key was already used with a different request body.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The request could not be recorded and the hold was released in full. You were not charged — safe to retry.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"get":{"tags":["Subscriptions"],"operationId":"listTopupOrders","summary":"List subscription requests","description":"Your recent subscription requests, newest first. This is the recovery path for a submission whose response was lost: it still shows up here, so resume polling it instead of paying twice. Free to call.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"How many requests to return. Clamped to 100."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["processing","completed","failed"]},"description":"Return only requests in this state."}],"responses":{"200":{"description":"Recent requests.","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll call."},"status":{"type":"string","enum":["processing","completed","failed"]},"listing_id":{"type":["string","null"]},"platform":{"type":["string","null"]},"title":{"type":["string","null"]},"account":{"type":"string"},"contact":{"type":["string","null"]},"price":{"type":"number","description":"NGN held in escrow."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True only once the request completed. Until then the price is a hold, not a charge."},"notes":{"type":["string","null"],"description":"What the fulfilling admin wrote — typically the reason a request failed."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","price","currency","charged"]}}},"required":["orders"]}}}},"400":{"description":"limit or status failed validation.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/topup/orders/{id}":{"get":{"tags":["Subscriptions"],"operationId":"getTopupOrder","summary":"Poll a subscription request","description":"Reads one request. Unlike a verification number, this call moves no money — it only reports where a human got to. 'processing' means still in the queue; 'completed' with charged: true is the end of the happy path; 'failed' means the hold went back untouched and 'notes' says why. Free to call.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the request was placed."}],"responses":{"200":{"description":"The request.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll call."},"status":{"type":"string","enum":["processing","completed","failed"]},"listing_id":{"type":["string","null"]},"platform":{"type":["string","null"]},"title":{"type":["string","null"]},"account":{"type":"string"},"contact":{"type":["string","null"]},"price":{"type":"number","description":"NGN held in escrow."},"currency":{"type":"string","enum":["NGN"]},"charged":{"type":"boolean","description":"True only once the request completed. Until then the price is a hold, not a charge."},"notes":{"type":["string","null"],"description":"What the fulfilling admin wrote — typically the reason a request failed."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","price","currency","charged"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No such request on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/servers":{"get":{"tags":["Boost"],"operationId":"listBoostServers","summary":"List boost servers","description":"The boost panels available to your account. Each carries its own catalog and prices, so read the catalog on the server you intend to order from. Free to call.","responses":{"200":{"description":"Configured servers.","content":{"application/json":{"schema":{"type":"object","properties":{"servers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["server-1","server-2"]},"label":{"type":"string"}}}}},"required":["servers"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/services":{"get":{"tags":["Boost"],"operationId":"listBoostServices","summary":"List boost services","description":"One server's catalog in NGN with the account's Premium discount already applied. Rates are per 1000 units: an order costs quantity / 1000 × rate_per_1000. Every entry carries the extra inputs its type needs in 'requires', and 'quantity_from' when the quantity is derived from a list rather than sent. A catalog runs to thousands of entries — narrow it with category and search rather than pulling all of it before every order. Free to call.","parameters":[{"name":"server","in":"query","required":false,"schema":{"type":"string","enum":["server-1","server-2"]},"description":"Which server to read. Defaults to the primary. Each server has its own catalog, prices and minimums, so a service id is only valid on the server it was read from. An unrecognised value is rejected rather than silently defaulted."},{"name":"category","in":"query","required":false,"schema":{"type":"string"},"description":"Exact category match, e.g. 'Instagram Followers'."},{"name":"search","in":"query","required":false,"schema":{"type":"string"},"description":"Case-insensitive substring match on the service name."}],"responses":{"200":{"description":"Matching services.","content":{"application/json":{"schema":{"type":"object","properties":{"services":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Pass as service_id. Only valid on this server."},"name":{"type":"string"},"category":{"type":"string"},"type":{"type":"string","description":"Panel service type — Default, Custom Comments, Mentions, Poll …"},"min":{"type":"integer"},"max":{"type":"integer"},"rate_per_1000":{"type":"number"},"currency":{"type":"string","enum":["NGN"]},"requires":{"type":"array","items":{"type":"string","enum":["comments","usernames","hashtag","username","answer_number"]},"description":"Extra fields this service needs on top of link and quantity."},"quantity_from":{"type":["string","null"],"enum":["comments","usernames",null],"description":"When set, do NOT send quantity — it is the number of lines in this list."}}}}},"required":["services"]}}}},"400":{"description":"Unknown server.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The panel's catalog is unavailable right now.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/orders":{"post":{"tags":["Boost"],"operationId":"createBoostOrder","summary":"Place a boost order","description":"Debits the wallet in full and submits the order to the panel. There is no escrow here: if the panel rejects the order the debit is reversed and nothing is recorded, but once accepted the money is spent and only comes back as a proportional refund for undelivered units. Delivery is never instant — a 200 means accepted and running, so poll GET /boost/orders/{id} while poll_after_ms is non-null. Send an Idempotency-Key: a replayed order is a second paid order.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"A unique value per purchase — a UUID is ideal. The first request stores its result; repeats replay it with an 'Idempotent-Replay: true' header instead of spending again. Scoped to your account, expires after 24 hours."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"service_id":{"type":"integer","description":"An id from /boost/services on the same server."},"link":{"type":"string","description":"The profile, post or video URL to deliver to."},"quantity":{"type":"integer","description":"Units to deliver, within the service's min and max. Omit for services with a quantity_from list."},"server":{"type":"string","enum":["server-1","server-2"],"description":"Defaults to the primary server."},"comments":{"type":["array","string"],"items":{"type":"string"},"description":"Custom Comments services: one comment per array entry (or per line). The quantity is the count."},"usernames":{"type":["array","string"],"items":{"type":"string"},"description":"Custom-list Mentions services: one username per array entry (or per line). The quantity is the count."},"hashtag":{"type":"string","description":"Hashtag-targeted Mentions services."},"username":{"type":"string","description":"Mentions services that pull from a profile's followers."},"answer_number":{"type":"string","description":"Poll services: which answer to vote for."}},"required":["service_id","link"]}}}},"responses":{"200":{"description":"Order accepted by the panel and charged.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll, cancel and refill calls."},"status":{"type":"string","description":"As last reported by the panel: Pending, In progress, Processing, Completed, Partial or Canceled."},"server":{"type":"string","enum":["server-1","server-2"]},"service_id":{"type":"integer"},"service_name":{"type":["string","null"]},"category":{"type":["string","null"]},"link":{"type":"string"},"quantity":{"type":"integer","description":"Units ordered. For list-driven services this is the number of lines you sent, not a value you chose."},"charge":{"type":"number","description":"NGN debited when the order was placed."},"refunded":{"type":"number","description":"NGN credited back so far for undelivered units. charge − refunded is what the order actually cost."},"currency":{"type":"string","enum":["NGN"]},"start_count":{"type":["integer","null"],"description":"The counter's value when the panel started, once it reports one."},"remains":{"type":["integer","null"],"description":"Units still undelivered, as last reported."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","quantity","charge","currency"]}}}},"400":{"description":"Malformed request, a missing type-specific field, a quantity outside the service's min/max, an unknown server, insufficient balance, or the panel refused the order. Nothing was charged — a debit taken before a panel refusal is reversed in full.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No such service_id on this server.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"A request with this Idempotency-Key is still in flight. Retry shortly to read its result.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"422":{"description":"This Idempotency-Key was already used with a different request body.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"The order is live at the panel but could not be recorded. Contact support with the Idempotency-Key rather than retrying.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"503":{"description":"The panel is unreachable. Nothing was charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"get":{"tags":["Boost"],"operationId":"listBoostOrders","summary":"List boost orders","description":"Your recent boost orders, newest first — the recovery path for an order whose response was lost. Statuses are whatever the panel last reported; this read does not poll upstream, so read one order to refresh it. Free to call.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"How many orders to return. Clamped to 100."},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"Exact status match, e.g. 'Completed', 'In progress', 'Partial', 'Canceled'."}],"responses":{"200":{"description":"Recent orders.","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll, cancel and refill calls."},"status":{"type":"string","description":"As last reported by the panel: Pending, In progress, Processing, Completed, Partial or Canceled."},"server":{"type":"string","enum":["server-1","server-2"]},"service_id":{"type":"integer"},"service_name":{"type":["string","null"]},"category":{"type":["string","null"]},"link":{"type":"string"},"quantity":{"type":"integer","description":"Units ordered. For list-driven services this is the number of lines you sent, not a value you chose."},"charge":{"type":"number","description":"NGN debited when the order was placed."},"refunded":{"type":"number","description":"NGN credited back so far for undelivered units. charge − refunded is what the order actually cost."},"currency":{"type":"string","enum":["NGN"]},"start_count":{"type":["integer","null"],"description":"The counter's value when the panel started, once it reports one."},"remains":{"type":["integer","null"],"description":"Units still undelivered, as last reported."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","quantity","charge","currency"]}}},"required":["orders"]}}}},"400":{"description":"limit failed validation.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/orders/{id}":{"get":{"tags":["Boost"],"operationId":"getBoostOrder","summary":"Poll a boost order","description":"Pulls the live status from the panel, stores it, and settles any refund the order is owed — so polling is what puts money back in the wallet when an order is cancelled or ends Partial. Safe to call repeatedly; a refund can never be issued twice. Free to call.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the order was placed."}],"responses":{"200":{"description":"The order, with its live status.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Pass this to the poll, cancel and refill calls."},"status":{"type":"string","description":"As last reported by the panel: Pending, In progress, Processing, Completed, Partial or Canceled."},"server":{"type":"string","enum":["server-1","server-2"]},"service_id":{"type":"integer"},"service_name":{"type":["string","null"]},"category":{"type":["string","null"]},"link":{"type":"string"},"quantity":{"type":"integer","description":"Units ordered. For list-driven services this is the number of lines you sent, not a value you chose."},"charge":{"type":"number","description":"NGN debited when the order was placed."},"refunded":{"type":"number","description":"NGN credited back so far for undelivered units. charge − refunded is what the order actually cost."},"currency":{"type":"string","enum":["NGN"]},"start_count":{"type":["integer","null"],"description":"The counter's value when the panel started, once it reports one."},"remains":{"type":["integer","null"],"description":"Units still undelivered, as last reported."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"poll_after_ms":{"type":["integer","null"],"description":"Milliseconds to wait before reading this resource again, or null once nothing further can change."}},"required":["id","status","quantity","charge","currency"]}}}},"400":{"description":"This order was never accepted by the panel.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No such order on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/orders/{id}/cancel":{"post":{"tags":["Boost"],"operationId":"cancelBoostOrder","summary":"Cancel a boost order","description":"Asks the panel to cancel. Cancellation is the panel's call: a 409 means it refused (already in progress, or a non-cancellable service) and the order keeps running with nothing refunded. When accepted, the refund for undelivered units is issued as soon as the panel reports the order Canceled or Partial — refund_issued says whether that happened here; if it is false, keep polling the order.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the order was placed."}],"responses":{"200":{"description":"The panel accepted the cancellation.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"refund_issued":{"type":"boolean"},"refund_amount":{"type":"number","description":"NGN credited back by this call."},"currency":{"type":"string","enum":["NGN"]}},"required":["id","status","refund_issued"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No such order on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"The panel refused to cancel. The order is unchanged and nothing was refunded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/boost/orders/{id}/refill":{"post":{"tags":["Boost"],"operationId":"refillBoostOrder","summary":"Request a refill","description":"Asks the panel to top a delivered order back up after drops. Free — no wallet movement either way. Only some services offer refills, and only inside their window, so a 409 with the panel's reason is a normal outcome.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The Neomarket id returned when the order was placed."}],"responses":{"200":{"description":"Refill requested.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"refill_id":{"type":["integer","null"],"description":"The panel's refill id, when it returns one."},"status":{"type":"string","enum":["requested"]}},"required":["id","status"]}}}},"401":{"description":"Missing, malformed, revoked or unknown API key.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"No such order on this account.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"The panel refused the refill — not offered for this service, or outside its window.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Per-key rate limit exceeded.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"502":{"description":"Upstream provider failed. You were not charged.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}}}}