# Nomerin Reseller API > REST API untuk membeli nomor virtual penerima OTP. Base URL https://api.nomerin.id. Auth: header `Authorization: Bearer nmr_...` (buat di dashboard Nomerin menu API Reseller). Semua harga IDR integer. Respons sukses `{success:true,data,meta?}`, gagal `{success:false,error:{code,message,details?}}`; cabangkan pada error.code. ## Alur 1. GET /v1/services -> pilih service_id. 2. GET /v1/countries?service_id= -> pilih country_id. 3. GET /v1/offers?service_id=&country_id= -> pilih price. 4. POST /v1/orders {service_id,country_id,price,external_id?} + header Idempotency-Key -> order status processing. 5. Webhook order.number (nomor keluar, status waiting_otp) lalu order.otp (OTP masuk, status success); atau polling GET /v1/orders/{id} tiap 3-5 detik. 6. Tanpa OTP: POST /v1/orders/{id}/cancel setelah cancel_available_at (2 menit) -> refunded; lewat expires_at order direfund otomatis. ## Endpoint - GET /v1/balance (tanpa parameter): Cek saldo. 120/menit. - GET /v1/services (tanpa parameter): Daftar layanan. 120/menit. - GET /v1/countries (service_id:integer): Daftar negara untuk satu layanan. 120/menit. - GET /v1/offers (service_id:integer, country_id:integer): Daftar harga untuk layanan + negara. 120/menit. - POST /v1/orders (Idempotency-Key:string?, service_id:integer, country_id:integer, price:integer, external_id:string?): Buat order nomor. 30/menit. - GET /v1/orders/{order_id} (order_id:integer): Detail dan status order. 120/menit. - GET /v1/orders (status:string?, external_id:string?, before_id:integer?, limit:integer?): Daftar order. 120/menit. - POST /v1/orders/{order_id}/cancel (order_id:integer): Batalkan order. 30/menit. ## Status order processing: Order diterima dan sedang dicarikan nomor. Biasanya selesai dalam beberapa detik, paling lama kurang lebih 80 detik.; waiting_otp: Nomor sudah keluar (field number terisi). Pakai nomornya lalu tunggu OTP. Boleh dibatalkan setelah cancel_available_at.; success: OTP masuk (otp_code terisi). Nomor masih bisa menerima OTP tambahan sampai expires_at, setiap OTP baru memicu webhook order.otp.; refunded: Tidak ada OTP sampai expires_at atau order dibatalkan. Saldo sudah dikembalikan penuh.; failed: Nomor tidak didapat setelah semua percobaan. Saldo sudah dikembalikan penuh. ## Objek order id (integer), external_id (string|null), status (string), service (object), country (object), price (integer), number (string|null), otp_code (string|null), otp_codes (array), otp_received_at (string|null), created_at (string), expires_at (string|null), cancel_available_at (string|null), refunded_at (string|null), failure_reason (string|null). failure_reason hanya NUMBER_UNAVAILABLE. ## Error code 401 UNAUTHORIZED; 401 KEY_REVOKED; 402 INSUFFICIENT_BALANCE; 404 NOT_FOUND; 404 SERVICE_NOT_FOUND; 404 COUNTRY_NOT_FOUND; 404 ORDER_NOT_FOUND; 409 OFFER_UNAVAILABLE; 409 IDEMPOTENCY_KEY_REUSED; 409 REQUEST_IN_PROGRESS; 409 CANCEL_NOT_ALLOWED; 409 CANCEL_TOO_EARLY; 409 OTP_ALREADY_RECEIVED; 422 VALIDATION_ERROR; 429 RATE_LIMIT_EXCEEDED; 429 TOO_MANY_ACTIVE_ORDERS; 429 ORDER_BLOCKED; 503 PURCHASE_DISABLED; 503 CANCEL_FAILED; 500 INTERNAL_ERROR ## Batasan Rate limit per API key per menit: baca 120, buat order 30, cancel 30; header X-RateLimit-Limit/Remaining/Reset dan Retry-After pada 429. Maksimal 10 order aktif per key. Idempotency-Key disimpan 24 jam; body berbeda -> IDEMPOTENCY_KEY_REUSED. ## Webhook POST JSON {event, created_at, order} ke URL https yang diatur di dashboard. Event: order.number, order.otp, order.refunded, order.failed, webhook.test. Header X-Nomerin-Event, X-Nomerin-Delivery, X-Nomerin-Timestamp, X-Nomerin-Signature (t=,v1=.'>). Hanya HTTP 200 dianggap sukses; selain itu dicoba ulang total 5 kali dengan jeda 5s, 15s, 40s, 90s. Bisa duplikat, dedupe dengan order.id+status+otp_code. ## Dokumen lengkap - [Dokumentasi lengkap Markdown](https://api.nomerin.id/docs.md) - [OpenAPI JSON](https://api.nomerin.id/openapi.json) - [OpenAPI YAML](https://api.nomerin.id/openapi.yaml) - [Halaman dokumentasi](https://api.nomerin.id/docs)