Stable v1 contract

MobileSimPortal API v1

Use this guide with the complete API reference. All requests use JSON and bearer authentication. Mutations also require a unique Idempotency-Key.

Authentication

curl -X POST https://mobilesimportal.com/api/create-token \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"login":"YOUR_LOGIN","password":"YOUR_PASSWORD"}'

Tokens expire after 24 hours and are scoped to account reads, rental reads/writes, and proxy reads/writes.

Long-term rental workflow

curl https://mobilesimportal.com/api/long-term-rentals/products \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_TOKEN'

curl -X POST https://mobilesimportal.com/api/long-term-rentals \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Idempotency-Key: 123e4567-e89b-42d3-a456-426614174000' \
  -H 'Content-Type: application/json' \
  -d '{"product_type":"unlimited","location_mode":"state","state":"NY"}'

For long-term rentals, omit location fields for Any US location, send location_mode: state with a two-letter state, or send zipcode for an explicit five-digit ZIP. Existing ZIP-only requests remain supported. Location is a preference, not an area-code guarantee.

Renew an existing mobile proxy

Read GET /api/mobile-proxies/{proxy} for the current renewal quote, then renew the same active proxy for its current plan. Use a new idempotency key for each intentional renewal and reuse that key after a transport failure. Automatic renewal and expired-proxy recovery are not supported.

curl -X POST https://mobilesimportal.com/api/mobile-proxies/4321/renew \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: renewal-unique-request-id' \
  -d '{"max_price":20.00}'

max_price is your accepted charge ceiling in credits. A successful response includes the updated expiry. If the outcome is pending (409), credit remains reserved: check the proxy status and contact support rather than sending a new key. Definitively rejected requests release reserved credit.

Retrieve an existing eSIM QR

Customers and resellers on any portal can retrieve their own eligible active eSIM rental’s existing activation image. This does not issue or purchase a new eSIM. Requires rentals:read and your account password.

POST /api/long-term-rentals/1234/esim-qr
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{"password":"YOUR_ACCOUNT_PASSWORD"}

The JSON response contains data.rental_id, data.mime_type (image/png) and data.image_base64. Decode the base64 as PNG, or display it with the data:image/png;base64, prefix. Keep the QR and password private; do not log or cache them. Five requests per minute, shared with the UI. No idempotency header is required. QR retrieval must be enabled; rental ownership and active eSIM eligibility are enforced.

Mobile proxy workflow

curl https://mobilesimportal.com/api/mobile-proxies/plans \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_TOKEN'

curl -X POST https://mobilesimportal.com/api/mobile-proxies \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Idempotency-Key: 123e4567-e89b-42d3-a456-426614174000' \
  -H 'Content-Type: application/json' \
  -d '{"plan":"day"}'

Track long-term activation

A purchase returns 202 Accepted, not an active rental. Generate a fresh UUID for each intentional purchase; the sample UUID below must not be reused for different purchases. Save the response:

{"success":true,"pending":true,
 "purchase_request_id":"123e4567-e89b-42d3-a456-426614174000",
 "status_url":"/api/long-term-rentals/purchase-requests/123e4567-e89b-42d3-a456-426614174000",
 "message":"Your Unlimited SMS mobile number is being provisioned. It will appear here after activation completes.",
 "balance":75.50}

Use the same account's bearer token with rentals:read:

GET /api/long-term-rentals/purchase-requests/123e4567-e89b-42d3-a456-426614174000

{"success":true,"data":{
 "purchase_request_id":"123e4567-e89b-42d3-a456-426614174000",
 "status":"completed","rental_id":1234,
 "message":"Your rental is ready.",
 "created_at":"2026-10-13T12:00:00-04:00",
 "updated_at":"2026-10-13T12:01:00-04:00"}}

States are pending, completed, failed, and unknown. rental_id is null unless completed. Then retrieve GET /api/long-term-rentals/1234. The purchase UUID is the original UUID Idempotency-Key, so existing pending requests can be queried even if their cached response predates these fields. Never use a new key to poll. Unknown outcomes need further checking; contact support if unresolved. Failed requests are terminal; contact support before another purchase. Poll with backoff within rate limits; no guaranteed activation deadline is promised.

One-time rental workflow

  1. Read GET /api/services, optional GET /api/states, and POST /api/rates/mobiles_rentals.
  2. POST /api/one-time-rent/request with service, optional state/markup, and a new idempotency key. Save request. A 201 can include mdn or status: Awaiting MDN.
  3. While awaiting a number, POST /api/one-time-rent/priority-request-mdn with the saved request ID. This read-only POST needs no idempotency key.
  4. POST /api/one-time-rent/message with request and mdn to read a message. Formatted or digits-only numbers are accepted. The legacy service field is ignored. Inspect success: HTTP 200 can mean received, still waiting, or not found.

Rejection requires a NEW request less than 15 minutes old. Reuse requires an earlier successful request; changing service can incur a new charge. Replies require a successful request updated within 30 minutes, cost $0.10, and legacy text handling truncates rather than rejecting long text. History uses numeric status filters but returns status labels; default limit is 100, and offset/limit must both be present to paginate. History and renewal legacy date strings use the application's configured timezone and do not embed an offset; do not interpret them as your device's local time. ISO timestamps carry their explicit offset.

OTR request IDs are not LTR rental IDs. Status and rejection retain a legacy opaque JSON payload under data; no stable nested schema is promised. Rates use dollar-prefixed strings; service prices can be numeric or a bulk-entitlement display string.

Authentication, errors and safe retries

Sign in on the portal associated with your customer/reseller account; ineligible roles or the wrong portal can return 400. Tokens last 24 hours. Account endpoints need account:read; rental reads and read-only POST lookups need rentals:read; rental mutations need rentals:write; proxy reads/writes need proxies:read/proxies:write. Every OpenAPI operation records its required ability. Current-token revocation does not revoke other tokens.

Always send Accept: application/json. The shared API budget is 240 requests/minute; token issuance is additionally limited to 10/minute per login/IP and QR to 5/minute per account. Respect 429 and Retry-After. Poll with backoff, not a tight loop.

Idempotency keys are scoped to the user and method/route; the exact URL and input must match. Allowed key characters are letters, digits, dot, underscore, colon and hyphen, maximum 128 characters. LTR purchase/reply keys must be UUIDs. Exact replays return the stored HTTP status/body and Idempotent-Replayed: true, including pending 202 responses. There is no guaranteed key-reset interval. A new key is a new intentional operation, not a retry strategy.

400/422 indicate validation or eligibility failures; 401 means authentication is required, 403 means insufficient scope/eligibility, and 404 hides missing/non-owned/ineligible resources. 402 means insufficient available credit. For 409 or uncertain network/5xx results, do not create another purchase or renewal: check the relevant status and contact support if unresolved. Reservations may remain until the outcome is known.

Rental and proxy lifecycle details

LTR renewal returns replayed, expires (legacy formatted date) and balance. Auto-renew returns the updated rental in data. Number change returns 202/pending; read the rental until its number changes, or contact support if unresolved. It has no separate public operation-status endpoint. LTR replies return sent, pending, duplicate and accept at most 160 UTF-8 bytes after trimming.

Proxy list/detail includes renewal_status. Details and successful mutations return connection, allowlist, renewal and capability fields. Expired proxies have connection: null; unavailable renewal prices can be null. To disable an allowlist, send {"addresses":[],"protocol":"socks5"}; addresses is required to be present and allows at most 16 IPv4 strings. Proxy IP rotation is request acceptance, not a guarantee that the observed IP has changed immediately. Cancellation, automatic proxy renewal, expired-proxy recovery and customer webhook subscriptions are not exposed by this API.

Compatibility and deprecation policy

Version 1 naming and response envelopes are stable. Backward-compatible fields may be added without notice. A breaking removal or rename receives at least 90 days of notice in this guide and the API changelog, except when immediate action is required for security or privacy.

Changelog