{"info":{"_postman_id":"42c7a0e4-668c-4193-aebc-002e5ae0d1f5","name":"SIMAREA API v1","description":"Every route of the SIMAREA API `v1`, generated from the same description of the API as the documentation page.\n\nSet the **apiKey** collection variable to your secret key and every request is ready to send — the collection's bearer auth reads it, so no request carries a credential of its own. **baseUrl** defaults to `https://0.0.0.0:3000/api/v1`.\n\nEvery path ends in a trailing slash and the slash is part of it: the unslashed form answers 308, and several HTTP clients drop the request body when they follow a redirect.\n\nDocumentation: https://0.0.0.0:3000/reseller/api/\n\nOpenAPI 3.1: https://0.0.0.0:3000/reseller/api/openapi.json","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json"},"auth":{"type":"bearer","bearer":[{"key":"token","value":"{{apiKey}}","type":"string"}]},"variable":[{"key":"baseUrl","value":"https://0.0.0.0:3000/api/v1","type":"string","description":"The API root for this deployment. Every request is built from it."},{"key":"apiKey","value":"","type":"secret","description":"Your secret key. Sent as a bearer token on every request in this collection."}],"item":[{"name":"eSIM data plans","description":"Destinations, plans, buying an eSIM and handing over the QR code.","item":[{"name":"List eSIM destinations","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/destinations/","host":["{{baseUrl}}"],"path":["catalog","destinations",""]},"description":"Every place an eSIM plan can cover — single countries, regions and global plans — in one list.\n\nBuild your destination mapping against `syncedPackageCount`, which counts what our supplier carries regardless of whether it is priced yet. `packageCount` counts only what is on sale.\n\nPermission required: **read**."},"response":[{"name":"List destinations","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/destinations/","host":["{{baseUrl}}"],"path":["catalog","destinations",""]},"description":"Every place an eSIM plan can cover — single countries, regions and global plans — in one list.\n\nBuild your destination mapping against `syncedPackageCount`, which counts what our supplier carries regardless of whether it is priced yet. `packageCount` counts only what is on sale.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"destinations\": [\n    {\n      \"slug\": \"thailand\",\n      \"kind\": \"country\",\n      \"name\": \"Thailand\",\n      \"countryCode\": \"th\",\n      \"isPopular\": true,\n      \"fromBundlePriceCents\": null,\n      \"fromPerDayPriceCents\": null,\n      \"packageCount\": 0,\n      \"syncedPackageCount\": 18,\n      \"isListed\": true\n    },\n    {\n      \"slug\": \"europe-esim\",\n      \"kind\": \"region\",\n      \"name\": \"Europe\",\n      \"countryCode\": null,\n      \"isPopular\": true,\n      \"fromBundlePriceCents\": null,\n      \"fromPerDayPriceCents\": null,\n      \"packageCount\": 0,\n      \"syncedPackageCount\": 26,\n      \"isListed\": true\n    }\n  ]\n}"}]},{"name":"List eSIM data plans","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/packages/?destination=thailand","host":["{{baseUrl}}"],"path":["catalog","packages",""],"query":[{"key":"destination","value":"thailand","description":"Narrow to one destination slug. An unknown slug is a 404.","disabled":false}]},"description":"The eSIM plans on sale, optionally for one destination. `code` is what you send back as `packageCode` when you buy.\n\nRead `pricingUnit` before you read `priceCents`. On a `bundle` the price is the total for the plan; on a `per_day` package it is a daily rate and you choose the term at purchase with `periodNum`.\n\n- This route currently returns an EMPTY LIST, and that is the correct answer rather than a fault. eSIM pricing is blocked on an unresolved unit question with our supplier, so no plan is priced and none is offered for sale. Your key authenticates, the route works, the list is empty. An eSIM purchase attempted today is refused and nothing is charged.\n- The destinations route answers in full in the meantime, so the mapping half of your integration can be built and tested now.\n\nPermission required: **read**."},"response":[{"name":"Plans for one destination","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/packages/?destination=thailand","host":["{{baseUrl}}"],"path":["catalog","packages",""],"query":[{"key":"destination","value":"thailand","description":"Narrow to one destination slug. An unknown slug is a 404.","disabled":false}]},"description":"The eSIM plans on sale, optionally for one destination. `code` is what you send back as `packageCode` when you buy.\n\nRead `pricingUnit` before you read `priceCents`. On a `bundle` the price is the total for the plan; on a `per_day` package it is a daily rate and you choose the term at purchase with `periodNum`.\n\n- This route currently returns an EMPTY LIST, and that is the correct answer rather than a fault. eSIM pricing is blocked on an unresolved unit question with our supplier, so no plan is priced and none is offered for sale. Your key authenticates, the route works, the list is empty. An eSIM purchase attempted today is refused and nothing is charged.\n- The destinations route answers in full in the meantime, so the mapping half of your integration can be built and tested now.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"packages\": []\n}"}]},{"name":"Buy","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Idempotency-Key","value":"{{$guid}}","type":"text","description":"One value per purchase intent, NOT per HTTP attempt. 8 to 200 characters of letters, digits and `_ . : -`; a UUID is ideal. Absent is a 400 — we never generate one for you.","disabled":false}],"url":{"raw":"{{baseUrl}}/orders/","host":["{{baseUrl}}"],"path":["orders",""]},"description":"One route, two bodies, told apart by `family`. The body carries no price: the order is priced from live supply at the moment of purchase, and the response tells you what was actually charged.\n\nA success is a 201 with the order read back AFTER it was created, so its `status` is current rather than the one it held a moment earlier.\n\n- The permission required is `order`, for a virtual number and an eSIM alike. A key without it gets a 403, and nothing is charged.\n- A slug that does not resolve is a 404. It is never quietly substituted for something near it.\n- Nothing is charged on any failure. Where a debit has already happened when the supplier fails, it is refunded automatically.\n\nPermission required: **order**.","body":{"mode":"raw","raw":"{\n  \"family\": \"esim\",\n  \"destinationSlug\": \"thailand\",\n  \"packageCode\": \"TH-7D-1GB\",\n  \"periodNum\": 7\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"Buy an eSIM data plan","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Idempotency-Key","value":"{{$guid}}","type":"text","description":"One value per purchase intent, NOT per HTTP attempt. 8 to 200 characters of letters, digits and `_ . : -`; a UUID is ideal. Absent is a 400 — we never generate one for you.","disabled":false}],"url":{"raw":"{{baseUrl}}/orders/","host":["{{baseUrl}}"],"path":["orders",""]},"description":"One route, two bodies, told apart by `family`. The body carries no price: the order is priced from live supply at the moment of purchase, and the response tells you what was actually charged.\n\nA success is a 201 with the order read back AFTER it was created, so its `status` is current rather than the one it held a moment earlier.\n\n- The permission required is `order`, for a virtual number and an eSIM alike. A key without it gets a 403, and nothing is charged.\n- A slug that does not resolve is a 404. It is never quietly substituted for something near it.\n- Nothing is charged on any failure. Where a debit has already happened when the supplier fails, it is refunded automatically.\n\nPermission required: **order**.","body":{"mode":"raw","raw":"{\n  \"family\": \"esim\",\n  \"destinationSlug\": \"thailand\",\n  \"packageCode\": \"TH-7D-1GB\",\n  \"periodNum\": 7\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"order\": {\n    \"publicId\": \"o_2wF6y9Bk4mTd\",\n    \"family\": \"esim\",\n    \"status\": \"provisioning\",\n    \"priceCents\": \"420\",\n    \"createdAt\": \"2026-08-24T09:31:47.104Z\",\n    \"completedAt\": null,\n    \"esim\": {\n      \"destinationSlug\": \"thailand\",\n      \"qrCodeUrl\": null,\n      \"acCode\": null,\n      \"smdpAddress\": null,\n      \"iccid\": null,\n      \"dataTotalMb\": \"1024\",\n      \"dataUsedMb\": \"0\",\n      \"expiresAt\": null\n    }\n  }\n}"}]},{"name":"Read one order","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/","host":["{{baseUrl}}"],"path":["orders",":publicId",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"One order and everything currently known about it, including every SMS received on a number order and the install details on an eSIM.\n\nThis is the route you poll while an order is in flight. There are no outbound webhooks in this version.\n\n- An order belonging to another account answers 404, not 403. A key can only ever see its own account's orders.\n- Poll no faster than the rate-limit headers allow.\n\nPermission required: **read**."},"response":[{"name":"An installable eSIM","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/","host":["{{baseUrl}}"],"path":["orders",":publicId",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"One order and everything currently known about it, including every SMS received on a number order and the install details on an eSIM.\n\nThis is the route you poll while an order is in flight. There are no outbound webhooks in this version.\n\n- An order belonging to another account answers 404, not 403. A key can only ever see its own account's orders.\n- Poll no faster than the rate-limit headers allow.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"order\": {\n    \"publicId\": \"o_2wF6y9Bk4mTd\",\n    \"family\": \"esim\",\n    \"status\": \"active\",\n    \"priceCents\": \"420\",\n    \"createdAt\": \"2026-08-24T09:31:47.104Z\",\n    \"completedAt\": null,\n    \"esim\": {\n      \"destinationSlug\": \"thailand\",\n      \"qrCodeUrl\": \"https://qr.example.net/8ac1f0e2b7.png\",\n      \"acCode\": \"LPA:1$smdp.example.net$K2-XXXXXXXX\",\n      \"smdpAddress\": \"smdp.example.net\",\n      \"iccid\": \"8900000000000000000\",\n      \"dataTotalMb\": \"1024\",\n      \"dataUsedMb\": \"37\",\n      \"expiresAt\": \"2026-08-31T09:33:02.000Z\"\n    }\n  }\n}"}]},{"name":"List your orders","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=esim","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"esim","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":true},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"response":[{"name":"Your eSIMs","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=esim","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"esim","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":true},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"orders\": [],\n  \"nextCursor\": null\n}"},{"name":"Page through every order","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=esim","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"esim","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":true},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"orders\": [ /* 200 orders */ ],\n  \"nextCursor\": \"MjAyNi0wOC0yNFQwOToxNDowMy4yMjFafG9fOGtRMm00WHI5ZExw\"\n}"}]},{"name":"Cancel and refund an order","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/cancel/","host":["{{baseUrl}}"],"path":["orders",":publicId","cancel",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"Stops an order and returns what it refunded. The rules are exactly the website's own cancel button — this route is not a second policy.\n\n- Canceling an order that our own expiry sweeper closed a moment earlier answers 200, not an error. You asked for it to stop; it has stopped.\n- An order that has already received an SMS cannot be canceled or refunded — the code you paid for arrived. That is a 409.\n- A rental that ran its full term refunds nothing, because it delivered everything it promised.\n\nPermission required: **read, plus order**."},"response":[{"name":"Already closed by the sweeper","originalRequest":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/cancel/","host":["{{baseUrl}}"],"path":["orders",":publicId","cancel",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"Stops an order and returns what it refunded. The rules are exactly the website's own cancel button — this route is not a second policy.\n\n- Canceling an order that our own expiry sweeper closed a moment earlier answers 200, not an error. You asked for it to stop; it has stopped.\n- An order that has already received an SMS cannot be canceled or refunded — the code you paid for arrived. That is a 409.\n- A rental that ran its full term refunds nothing, because it delivered everything it promised.\n\nPermission required: **read, plus order**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"cancel\": {\n    \"status\": \"expired\",\n    \"refundedCents\": \"0\"\n  }\n}"}]}]},{"name":"Virtual numbers","description":"Rent a dedicated non-VoIP line by the term and read its messages.","item":[{"name":"List every country","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/countries/","host":["{{baseUrl}}"],"path":["catalog","countries",""]},"description":"Every country we sell numbers in, popular ones first — the same order the website uses, so a list you cache and a page a customer reads agree.\n\nIt is NOT filtered by what is in stock this minute. That is a property of one family at one moment and the offers route answers it; a country list that shrank when a pool emptied would silently break a mapping you built last week.\n\nPermission required: **read**."},"response":[{"name":"List countries","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/countries/","host":["{{baseUrl}}"],"path":["catalog","countries",""]},"description":"Every country we sell numbers in, popular ones first — the same order the website uses, so a list you cache and a page a customer reads agree.\n\nIt is NOT filtered by what is in stock this minute. That is a property of one family at one moment and the offers route answers it; a country list that shrank when a pool emptied would silently break a mapping you built last week.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"countries\": [\n    { \"slug\": \"usa\", \"name\": \"United States\", \"code\": \"us\", \"phoneCode\": \"+1\", \"isPopular\": true },\n    { \"slug\": \"united-kingdom\", \"name\": \"United Kingdom\", \"code\": \"gb\", \"phoneCode\": \"+44\", \"isPopular\": true }\n  ]\n}"}]},{"name":"List every service","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/services/","host":["{{baseUrl}}"],"path":["catalog","services",""]},"description":"Every app or website a number can be bought for, popular ones first. `slug` is what a purchase body takes.\n\nPermission required: **read**."},"response":[{"name":"List services","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/services/","host":["{{baseUrl}}"],"path":["catalog","services",""]},"description":"Every app or website a number can be bought for, popular ones first. `slug` is what a purchase body takes.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"services\": [\n    { \"slug\": \"telegram\", \"name\": \"Telegram\", \"isPopular\": true },\n    { \"slug\": \"whatsapp\", \"name\": \"WhatsApp\", \"isPopular\": true }\n  ]\n}"}]},{"name":"Live prices and stock","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/offers/?family=virtual_number&country=usa","host":["{{baseUrl}}"],"path":["catalog","offers",""],"query":[{"key":"family","value":"virtual_number","description":"Which product to price.","disabled":false},{"key":"country","value":"usa","description":"Narrow to one country slug.","disabled":false},{"key":"service","value":"telegram","description":"Narrow to one service slug.","disabled":true}]},"description":"What can be bought right now and for how much. Each row is the cheapest live price for a country, a service and a term across every supplier we have enabled.\n\n`family` is required and there is no \"all families\" mode: the families do not share a price shape, and a single list would force you to branch on a field anyway.\n\n- A slug that does not exist is a 404, not an empty list. An unknown `family` is a 400. Neither is ever silently widened to \"everything\".\n- Prices move with supply. Quote from this route at the moment you show a price, and do not cache it for longer than you would be happy to be wrong for.\n\nPermission required: **read**."},"response":[{"name":"Virtual number prices","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/catalog/offers/?family=virtual_number&country=usa","host":["{{baseUrl}}"],"path":["catalog","offers",""],"query":[{"key":"family","value":"virtual_number","description":"Which product to price.","disabled":false},{"key":"country","value":"usa","description":"Narrow to one country slug.","disabled":false},{"key":"service","value":"telegram","description":"Narrow to one service slug.","disabled":true}]},"description":"What can be bought right now and for how much. Each row is the cheapest live price for a country, a service and a term across every supplier we have enabled.\n\n`family` is required and there is no \"all families\" mode: the families do not share a price shape, and a single list would force you to branch on a field anyway.\n\n- A slug that does not exist is a 404, not an empty list. An unknown `family` is a 400. Neither is ever silently widened to \"everything\".\n- Prices move with supply. Quote from this route at the moment you show a price, and do not cache it for longer than you would be happy to be wrong for.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"offers\": [\n    {\n      \"family\": \"virtual_number\",\n      \"countrySlug\": \"usa\",\n      \"serviceSlug\": null,\n      \"durationSlug\": \"oneWeek\",\n      \"priceCents\": \"900\",\n      \"stock\": null\n    },\n    {\n      \"family\": \"virtual_number\",\n      \"countrySlug\": \"usa\",\n      \"serviceSlug\": null,\n      \"durationSlug\": \"oneMonth\",\n      \"priceCents\": \"2400\",\n      \"stock\": null\n    }\n  ]\n}"}]},{"name":"Buy","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Idempotency-Key","value":"{{$guid}}","type":"text","description":"One value per purchase intent, NOT per HTTP attempt. 8 to 200 characters of letters, digits and `_ . : -`; a UUID is ideal. Absent is a 400 — we never generate one for you.","disabled":false}],"url":{"raw":"{{baseUrl}}/orders/","host":["{{baseUrl}}"],"path":["orders",""]},"description":"One route, two bodies, told apart by `family`. The body carries no price: the order is priced from live supply at the moment of purchase, and the response tells you what was actually charged.\n\nA success is a 201 with the order read back AFTER it was created, so its `status` is current rather than the one it held a moment earlier.\n\n- The permission required is `order`, for a virtual number and an eSIM alike. A key without it gets a 403, and nothing is charged.\n- A slug that does not resolve is a 404. It is never quietly substituted for something near it.\n- Nothing is charged on any failure. Where a debit has already happened when the supplier fails, it is refunded automatically.\n\nPermission required: **order**.","body":{"mode":"raw","raw":"{\n  \"family\": \"virtual_number\",\n  \"countrySlug\": \"usa\",\n  \"serviceSlug\": null,\n  \"duration\": \"oneWeek\",\n  \"autoRenew\": false\n}","options":{"raw":{"language":"json"}}}},"response":[{"name":"Rent a virtual number","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Idempotency-Key","value":"{{$guid}}","type":"text","description":"One value per purchase intent, NOT per HTTP attempt. 8 to 200 characters of letters, digits and `_ . : -`; a UUID is ideal. Absent is a 400 — we never generate one for you.","disabled":false}],"url":{"raw":"{{baseUrl}}/orders/","host":["{{baseUrl}}"],"path":["orders",""]},"description":"One route, two bodies, told apart by `family`. The body carries no price: the order is priced from live supply at the moment of purchase, and the response tells you what was actually charged.\n\nA success is a 201 with the order read back AFTER it was created, so its `status` is current rather than the one it held a moment earlier.\n\n- The permission required is `order`, for a virtual number and an eSIM alike. A key without it gets a 403, and nothing is charged.\n- A slug that does not resolve is a 404. It is never quietly substituted for something near it.\n- Nothing is charged on any failure. Where a debit has already happened when the supplier fails, it is refunded automatically.\n\nPermission required: **order**.","body":{"mode":"raw","raw":"{\n  \"family\": \"virtual_number\",\n  \"countrySlug\": \"usa\",\n  \"serviceSlug\": null,\n  \"duration\": \"oneWeek\",\n  \"autoRenew\": false\n}","options":{"raw":{"language":"json"}}}},"status":"Created","code":201,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"order\": {\n    \"publicId\": \"o_5rT8w1Nq3vHc\",\n    \"family\": \"virtual_number\",\n    \"status\": \"active\",\n    \"priceCents\": \"900\",\n    \"createdAt\": \"2026-08-24T09:20:11.550Z\",\n    \"completedAt\": null,\n    \"rental\": {\n      \"phone\": \"+12025550188\",\n      \"countrySlug\": \"usa\",\n      \"serviceSlug\": null,\n      \"durationSlug\": \"oneWeek\",\n      \"rentedUntil\": \"2026-08-31T09:20:11.550Z\",\n      \"autoRenew\": false,\n      \"messages\": []\n    }\n  }\n}"}]},{"name":"Read one order","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/","host":["{{baseUrl}}"],"path":["orders",":publicId",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"One order and everything currently known about it, including every SMS received on a number order and the install details on an eSIM.\n\nThis is the route you poll while an order is in flight. There are no outbound webhooks in this version.\n\n- An order belonging to another account answers 404, not 403. A key can only ever see its own account's orders.\n- Poll no faster than the rate-limit headers allow.\n\nPermission required: **read**."},"response":[{"name":"An installable eSIM","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/","host":["{{baseUrl}}"],"path":["orders",":publicId",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"One order and everything currently known about it, including every SMS received on a number order and the install details on an eSIM.\n\nThis is the route you poll while an order is in flight. There are no outbound webhooks in this version.\n\n- An order belonging to another account answers 404, not 403. A key can only ever see its own account's orders.\n- Poll no faster than the rate-limit headers allow.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"order\": {\n    \"publicId\": \"o_2wF6y9Bk4mTd\",\n    \"family\": \"esim\",\n    \"status\": \"active\",\n    \"priceCents\": \"420\",\n    \"createdAt\": \"2026-08-24T09:31:47.104Z\",\n    \"completedAt\": null,\n    \"esim\": {\n      \"destinationSlug\": \"thailand\",\n      \"qrCodeUrl\": \"https://qr.example.net/8ac1f0e2b7.png\",\n      \"acCode\": \"LPA:1$smdp.example.net$K2-XXXXXXXX\",\n      \"smdpAddress\": \"smdp.example.net\",\n      \"iccid\": \"8900000000000000000\",\n      \"dataTotalMb\": \"1024\",\n      \"dataUsedMb\": \"37\",\n      \"expiresAt\": \"2026-08-31T09:33:02.000Z\"\n    }\n  }\n}"}]},{"name":"List your orders","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=virtual_number&open=1","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"virtual_number","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"1","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":false},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"response":[{"name":"Virtual numbers you hold","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=virtual_number&open=1","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"virtual_number","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"1","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":false},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"orders\": [\n    {\n      \"publicId\": \"o_5rT8w1Nq3vHc\",\n      \"family\": \"virtual_number\",\n      \"status\": \"active\",\n      \"priceCents\": \"900\",\n      \"createdAt\": \"2026-08-19T11:02:44.008Z\",\n      \"completedAt\": null,\n      \"rental\": {\n        \"phone\": \"+12025550188\",\n        \"countrySlug\": \"usa\",\n        \"serviceSlug\": null,\n        \"durationSlug\": \"oneWeek\",\n        \"rentedUntil\": \"2026-08-26T11:02:44.008Z\",\n        \"autoRenew\": true,\n        \"messages\": []\n      }\n    }\n  ],\n  \"nextCursor\": null\n}"},{"name":"Page through every order","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/orders/?family=virtual_number&open=1","host":["{{baseUrl}}"],"path":["orders",""],"query":[{"key":"family","value":"virtual_number","description":"Only this product family. Absent means every family.","disabled":false},{"key":"open","value":"1","description":"`1` or `true` returns only orders still in flight. Absent means no filter, which is not the same request as `open=0`.","disabled":false},{"key":"limit","value":"100","description":"1 to 200. Defaults to 50.","disabled":true},{"key":"cursor","value":"","description":"The `nextCursor` from the previous page. Opaque — do not parse it or construct one. A malformed value is a 400 rather than a silent restart at page one.","disabled":true}]},"description":"Your orders, newest first, across every family unless you narrow it. This is also the eSIM list and the number list — there is no separate route for either, because two doors onto one list are two things to keep in step.\n\nPages are walked with `cursor`. Send the `nextCursor` from the previous response to get the next page; `nextCursor` is `null` on the last one.\n\n- Keep the filters identical while you page. Changing `family` or `open` mid-walk makes the cursor mean something you did not intend.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"orders\": [ /* 200 orders */ ],\n  \"nextCursor\": \"MjAyNi0wOC0yNFQwOToxNDowMy4yMjFafG9fOGtRMm00WHI5ZExw\"\n}"}]},{"name":"Cancel and refund an order","request":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/cancel/","host":["{{baseUrl}}"],"path":["orders",":publicId","cancel",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"Stops an order and returns what it refunded. The rules are exactly the website's own cancel button — this route is not a second policy.\n\n- Canceling an order that our own expiry sweeper closed a moment earlier answers 200, not an error. You asked for it to stop; it has stopped.\n- An order that has already received an SMS cannot be canceled or refunded — the code you paid for arrived. That is a 409.\n- A rental that ran its full term refunds nothing, because it delivered everything it promised.\n\nPermission required: **read, plus order**."},"response":[{"name":"Already closed by the sweeper","originalRequest":{"method":"POST","header":[],"url":{"raw":"{{baseUrl}}/orders/:publicId/cancel/","host":["{{baseUrl}}"],"path":["orders",":publicId","cancel",""],"variable":[{"key":"publicId","value":"o_8kQ2m4Xr9dLp","description":"The order's `o_…` id."}]},"description":"Stops an order and returns what it refunded. The rules are exactly the website's own cancel button — this route is not a second policy.\n\n- Canceling an order that our own expiry sweeper closed a moment earlier answers 200, not an error. You asked for it to stop; it has stopped.\n- An order that has already received an SMS cannot be canceled or refunded — the code you paid for arrived. That is a 409.\n- A rental that ran its full term refunds nothing, because it delivered everything it promised.\n\nPermission required: **read, plus order**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"cancel\": {\n    \"status\": \"expired\",\n    \"refundedCents\": \"0\"\n  }\n}"}]}]},{"name":"Account","description":"Your balance, and checking what a key can do.","item":[{"name":"Read your prepaid balance","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/balance/","host":["{{baseUrl}}"],"path":["balance",""]},"description":"Everything you buy — on the API and on the website — is paid for out of one prepaid USD balance. This is that balance.\n\nCheck it before a batch of purchases rather than after a failure: a purchase that cannot be covered is refused with `insufficient_funds`, and that error carries the exact shortfall so you can top up by the right amount.\n\nPermission required: **read**."},"response":[{"name":"Read the balance","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/balance/","host":["{{baseUrl}}"],"path":["balance",""]},"description":"Everything you buy — on the API and on the website — is paid for out of one prepaid USD balance. This is that balance.\n\nCheck it before a batch of purchases rather than after a failure: a purchase that cannot be covered is refused with `insufficient_funds`, and that error carries the exact shortfall so you can top up by the right amount.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"balance\": {\n    \"currency\": \"USD\",\n    \"balanceCents\": \"12500\",\n    \"referralBalanceCents\": \"0\"\n  }\n}"}]},{"name":"Check your key and discover the API","request":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/","host":["{{baseUrl}}"],"path":[""]},"description":"Answers what this version is, where its machine-readable descriptions live, and exactly what the key you just used is allowed to do — including its rate limit.\n\nCall it first when you set an integration up. A 200 means the key is live, carries the permissions it lists, and belongs to an account in good standing; a 401 means it is missing, unknown, revoked, expired, or belongs to a suspended account.\n\nPermission required: **read**."},"response":[{"name":"Check a key","originalRequest":{"method":"GET","header":[],"url":{"raw":"{{baseUrl}}/","host":["{{baseUrl}}"],"path":[""]},"description":"Answers what this version is, where its machine-readable descriptions live, and exactly what the key you just used is allowed to do — including its rate limit.\n\nCall it first when you set an integration up. A 200 means the key is live, carries the permissions it lists, and belongs to an account in good standing; a 401 means it is missing, unknown, revoked, expired, or belongs to a suspended account.\n\nPermission required: **read**."},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"content-type","value":"application/json; charset=utf-8"},{"key":"x-request-id","value":"3f0b7c11-4a2e-4c6d-9d24-a7e0e5b1c9f4"},{"key":"x-api-version","value":"v1"},{"key":"cache-control","value":"no-store"},{"key":"x-ratelimit-limit","value":"60"},{"key":"x-ratelimit-remaining","value":"57"},{"key":"x-ratelimit-reset","value":"1755273600"}],"cookie":[],"body":"{\n  \"api\": {\n    \"version\": \"v1\",\n    \"documentationUrl\": \"https://simarea.com/reseller/api/\",\n    \"openapiUrl\": \"https://simarea.com/reseller/api/openapi.json\",\n    \"postmanUrl\": \"https://simarea.com/reseller/api/simarea.postman_collection.json\",\n    \"families\": [\"virtual_number\", \"esim\"],\n    \"key\": {\n      \"keyId\": \"a1b2c3d4e5f6\",\n      \"permissions\": [\"read\", \"order\"],\n      \"rateLimit\": 60\n    }\n  }\n}"}]}]}]}