Apply

Partner API · v1

Build your telecom brand
with one API.

Everything your partner panel does, from your own software: eSIMs, numbers, SIP trunks, your balance, rate cards and signed webhooks — in a live and a sandbox environment.

54operations
27webhook events
2environments
OpenAPI3.1.0 contract

Overview

Base URLhttps://miragetel.com/api/v1/partner
FormatJSON in, JSON out. Amounts are integer cents.
AuthYour key in X-Api-Key
Sandboxmtp_test_… keys, play money, every endpoint

One API serves your software and your partner panel: anything a person of your team can do in the panel, your code can do with a key. Every object belongs to your account; an id of another account answers “not found”.

Quickstart

  1. Get a sandbox keyIn your partner panel: Developers → Sandbox → New key. It is shown once — keep it in your secrets.
    curl https://miragetel.com/api/v1/partner/account \
      -H "X-Api-Key: mtp_test_…"
  2. Tell us where to send eventsAdd a webhook; its signing secret comes back in this answer only.
    curl -X POST https://miragetel.com/api/v1/partner/webhooks \
      -H "X-Api-Key: mtp_test_…" \
      -H "Idempotency-Key: hook-1" \
      -H "Content-Type: application/json" \
      -d '{"url":"https://your-server.example/miragetel","events":["esim.*"]}'
  3. Issue your first eSIMThe sandbox issues at once with a test activation code; esim.issued arrives at your webhook.
    curl -X POST https://miragetel.com/api/v1/partner/esims \
      -H "X-Api-Key: mtp_test_…" \
      -H "Idempotency-Key: order-1001" \
      -H "Content-Type: application/json" \
      -d '{"packageId": 4521, "reference": "ORDER-1001"}'

Then switch the key to mtp_live_… — the same code, real eSIMs, your real balance.

Authentication

Send your key in the X-Api-Key header on every request. Keys are issued in the partner panel and shown once; revoke and rotate them there. A key carries its environment and its scopes — esims:write, wallet:read… — and a request outside them answers 403 INSUFFICIENT_SCOPE naming the scope it needs.

Environments

Live · mtp_live_…Real eSIMs, numbers and calls, paid from your prepaid balance.
Sandbox · mtp_test_…The same endpoints and answers with play money and test objects. Nothing reaches an operator or your balance.

Idempotency

Every request that creates or pays needs an Idempotency-Key header — any unique string up to 120 characters. A retry with the same key and the same body gets the first answer back with Idempotent-Replayed: true: never a second order or a second charge. The same key with a different body answers 409 IDEMPOTENCY_KEY_REUSED; a key whose first request is still running answers 409 IDEMPOTENCY_IN_PROGRESS.

Errors

One shape for every error, with the same requestId in the X-Request-Id header — quote it when you write to us.

{
  "error": { "code": "INSUFFICIENT_SCOPE", "message": "This needs the rates:read scope.", "scope": "rates:read" },
  "requestId": "req_8Jx2…"
}
HTTPCodesMeaning
400INVALID_…, IDEMPOTENCY_KEY_REQUIREDThe request is wrong; the message says which field.
401UNAUTHORIZED, API_KEY_INVALIDNo key, or a key that is not one of yours (revoked, expired, or the wrong environment prefix).
403INSUFFICIENT_SCOPE, PARTNER_SUSPENDED, PARTNER_INACTIVEThe key lacks the scope (error.scope names it); a suspended account reads but changes nothing.
404NOT_FOUNDNo such object for your account — an object of another account is never found.
409IDEMPOTENCY_KEY_REUSED, IDEMPOTENCY_IN_PROGRESS, BALANCE_CAP_EXCEEDEDThe same Idempotency-Key with another body, the first request still running, or a balance that would pass $2,000.
429RATE_LIMITEDMore than 600 requests a minute for this key. Retry-After says when.
500INTERNAL_ERRORSomething failed on our side. Retry with the same Idempotency-Key; if it persists, write to us with the requestId.

Limits and pages

  • 600 requests a minute per key or panel person; past it, 429 RATE_LIMITED with Retry-After.
  • Lists answer newest first with ?limit (up to 200); the transaction log pages with ?before=<id>, the event log with ?after=<id>.
  • Amounts are integer cents (…Minor); per-minute voice rates are decimal dollars.

Webhooks

We POST each event you subscribed to as JSON — id, type, environment, object, data, createdAt. Answer any 2xx. A failed delivery is retried for 24 hours (30 s, 2 min, 10 min, 30 min, then hourly); 50 failures in a row pause the webhook. The address must be public HTTPS; redirects are not followed. Every event also stays in GET /events for 90 days.

X-MirageTel-Eventthe event type, e.g. esim.issued
X-MirageTel-Deliverythis delivery’s id (a retry keeps it)
X-MirageTel-Environmentlive or test
X-MirageTel-TimestampUnix seconds when signed
X-MirageTel-SignatureHMAC-SHA256 hex with your webhook secret over timestamp + "." + raw body

Verify the signature

const crypto = require('crypto');

// rawBody: the request body exactly as received, before any JSON parsing.
function fromMirageTel(headers, rawBody, secret) {
  const ts = headers['x-miragetel-timestamp'];
  const sig = String(headers['x-miragetel-signature'] || '');
  const expected = crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === expected.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Event types

Subscribe to a type, a family (esim.*) or everything (*). A payload names no operator and no cost — only what the API itself answers.

esim.issuedesim.failedesim.installedesim.status.changedesim.usage.thresholdesim.topup.completedesim.topup.failedesim.cancellednumber.orderednumber.activenumber.registration.requirednumber.registration.approvednumber.registration.rejectednumber.expiringnumber.cancelledend_user.updatedtrunk.createdtrunk.spend_cap.reachedcall.completedtext.receivedtext.status.changedbalance.lowtopup.completedstatement.issuedshop.order.completedshop.order.failedwebhook.test

Account and balance

Who you are, what you may do, and your money.

GET/accountaccount:read

The partner account, its services and what this key or person may do

Partner API. Authenticated by a partner key in X-Api-Key (mtp_live_…, mtp_test_…) or by the session of one of the partner's people (the panel) with X-Partner-Environment. Errors are { "error": { "code", "message" }, "requestId" }; every response carries X-Request-Id. 600 requests a minute per key or person. Scope account:read.

Request

No parameters.

Responses

  • 200The account.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 429RATE_LIMITED — more than 600 requests a minute for this key or person. Retry-After says when.
Response fields
idstring
namestring
legalNamestring
statusstring: active, suspended
countrystring | null
websitestring | null
environmentstring: live, test
servicesarray of object
youobject
limitsobject
supportobject
Request
curl "https://miragetel.com/api/v1/partner/account" \
  -H "X-Api-Key: mtp_test_…"
PATCH/accountwallet:write

Set the low-balance alert line

Scope wallet:write. A debit that takes the live balance below lowBalanceAlertMinor sends balance.low (and a mail to your admins and finance people) once per crossing. 0 switches it off. USD 50 by default.

Request

FieldInType
lowBalanceAlertMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.bodyinteger (cents)required

Responses

  • 200The account.
  • 400INVALID_AMOUNT or NOTHING_TO_CHANGE
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
idstring
namestring
legalNamestring
statusstring: active, suspended
countrystring | null
websitestring | null
environmentstring: live, test
servicesarray of object
youobject
limitsobject
supportobject
Request
curl -X PATCH "https://miragetel.com/api/v1/partner/account" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"lowBalanceAlertMinor":2000}'
GET/balancewallet:read

The prepaid balance — live, or the sandbox's virtual one

Scope wallet:read. A balance holds at most USD 2,000. In the sandbox the balance is virtual.

Request

No parameters.

Responses

  • 200The balance.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring: live, test
balanceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
heldMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
availableMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
capMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
headroomMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
Request
curl "https://miragetel.com/api/v1/partner/balance" \
  -H "X-Api-Key: mtp_test_…"
GET/transactionswallet:read

Money in and out of the balance, newest first

Scope wallet:read. Page with before (the last id you have).

Request

FieldInType
beforequerystring
limitqueryinteger

Responses

  • 200A page of transactions.
  • 400INVALID_CURSOR
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring: live, test
dataarray of object
hasMoreboolean
nextBeforestring | null
Request
curl "https://miragetel.com/api/v1/partner/transactions" \
  -H "X-Api-Key: mtp_test_…"
POST/sandbox/balancesandbox

Set the sandbox's virtual balance

Only in the sandbox (mtp_test_ key or X-Partner-Environment test). Up to USD 2,000. Nothing is money.

Request

FieldInType
balanceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.bodyinteger (cents)

Responses

  • 200The new sandbox balance.
  • 400INVALID_AMOUNT
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 409SANDBOX_ONLY — this is a live key or the live environment
Response fields
balanceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
environmentstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/sandbox/balance" \
  -H "X-Api-Key: mtp_test_…"

Top-ups, receipts and statements

Fund your prepaid balance by card, USDT or bank transfer.

GET/topupswallet:read

Your top-ups, newest first, with the room left under the cap

Scope wallet:read.

Request

FieldInType
limitqueryinteger

Responses

  • 200The top-ups.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
capMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
balanceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
pendingMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
headroomMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
Request
curl "https://miragetel.com/api/v1/partner/topups" \
  -H "X-Api-Key: mtp_test_…"
POST/topupswallet:writeIdempotency-Key

Add funds to the balance — card, USDT or bank transfer

Scope wallet:write. Live: a payment request on your account and what you need to pay it — checkoutUrl (card), usdt (the exact amount to send and our TRON address; the amount identifies your payment), or bank (the details and the reference to quote). Credited when the money arrives, with a receipt in your company's name and a topup.completed event. The balance holds at most USD 2,000 (counting top-ups not yet paid): above it, 409. Sandbox: the play-money balance goes up at once.

Request

FieldInType
methodbodystring: card, usdt_trc20, bankrequired
amountMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.bodyinteger (cents)required

Responses

  • 201The top-up and how to pay it.
  • 400INVALID_METHOD, INVALID_AMOUNT or IDEMPOTENCY_KEY_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 409BALANCE_CAP_EXCEEDED (error.details.headroomMinor says what fits) or an Idempotency-Key conflict
  • 502PAYMENT_PROVIDER_ERROR — the card page could not be opened
  • 503METHOD_UNAVAILABLE or AMOUNT_UNAVAILABLE
Response fields
idstring
referencestring
methodstring: card, usdt_trc20, bank
environmentstring: live, test
amountMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
statusstring: pending, completed, rejected, expired
createdAtstring
resolvedAtstring | null
expiresAtstring | null
checkoutUrlCard onlystring
usdtobject
bankobject
creditedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
returnedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
Request
curl -X POST "https://miragetel.com/api/v1/partner/topups" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"method":"card","amountMinor":5000}'
GET/topups/{id}wallet:read

One top-up and where it stands

Scope wallet:read.

Request

FieldInType
idpathstringrequired

Responses

  • 200The top-up.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
referencestring
methodstring: card, usdt_trc20, bank
environmentstring: live, test
amountMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
statusstring: pending, completed, rejected, expired
createdAtstring
resolvedAtstring | null
expiresAtstring | null
checkoutUrlCard onlystring
usdtobject
bankobject
creditedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
returnedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
Request
curl "https://miragetel.com/api/v1/partner/topups/<id>" \
  -H "X-Api-Key: mtp_test_…"
POST/topups/{id}/claimwallet:write

I have paid — name the USDT transaction

Scope wallet:write. For a USDT top-up whose amount could not be matched (for example a wallet that converted the figure): the transaction is read from the chain and every check of the automatic path applies before anything is credited. What arrived is credited, rounded up to the cent; less than asked is settled by a person.

Request

FieldInType
idpathstringrequired
txid64 hex charactersbodystringrequired

Responses

  • 200Credited.
  • 400INVALID_TXID
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND or NOT_FOUND_ON_CHAIN
  • 409REQUEST_NOT_PENDING, ALREADY_CREDITED, TOO_RECENT, AMOUNT_TOO_LOW, NOT_USDT, NOT_SENT_TO_US, USDT_ONLY or LIVE_ONLY
  • 503CHAIN_UNREACHABLE or NO_BUSINESS_ADDRESS
Response fields
idstring
referencestring
methodstring: card, usdt_trc20, bank
environmentstring: live, test
amountMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
statusstring: pending, completed, rejected, expired
createdAtstring
resolvedAtstring | null
expiresAtstring | null
checkoutUrlCard onlystring
usdtobject
bankobject
creditedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
returnedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
Request
curl -X POST "https://miragetel.com/api/v1/partner/topups/<id>/claim" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"txid":"<transaction hash>"}'
GET/receiptswallet:read

Receipts for every top-up, issued to your company

Scope wallet:read. url opens the document without signing in.

Request

FieldInType
limitqueryinteger

Responses

  • 200The receipts.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/receipts" \
  -H "X-Api-Key: mtp_test_…"
GET/statementswallet:read

Monthly statements — what was charged, by category

Scope wallet:read. A statement lists charges only; money paid in is on the receipts.

Request

FieldInType
limitqueryinteger

Responses

  • 200The statements.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/statements" \
  -H "X-Api-Key: mtp_test_…"

eSIMs

Issue, deliver, top up and cancel data eSIMs for your customers.

GET/esims/packagesesims:read

Every eSIM package you can buy, at your price

Scope esims:read. The same list as GET /partner/rates/esim: available says whether it can be bought this minute.

Request

FieldInType
countryquerystring

Responses

  • 200The packages.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
currencystring
Request
curl "https://miragetel.com/api/v1/partner/esims/packages" \
  -H "X-Api-Key: mtp_test_…"
GET/esimsesims:read

Your eSIMs, newest first

Scope esims:read. Filter by status or by your reference.

Request

FieldInType
statusquerystring: processing, issued, installed, used_up, expired, closed, cancelled, failed
referencequerystring
limitqueryinteger

Responses

  • 200The eSIMs.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/esims" \
  -H "X-Api-Key: mtp_test_…"
POST/esimsesims:writeIdempotency-Key

Buy an eSIM for your customer, from your balance

Scope esims:write. Answers at once with the eSIM in processing; it becomes issued (or failed, nothing charged) when the operator answers — usually within seconds — and esim.issued carries the activation code, the iPhone install link and the QR path. reference is your own id for the sale, unique on your account. Needs the eSIM service switched on for your account. Sandbox: issued at once with a test activation code; play money only.

Request

FieldInType
packageIdbodyintegerrequired
referencebodystring
activationDateOnly for a plan that needs one.bodystring

Responses

  • 201The eSIM.
  • 400INVALID_PACKAGE, INVALID_REFERENCE, INVALID_ACTIVATION_DATE, ACTIVATION_DATE_REQUIRED or IDEMPOTENCY_KEY_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 402INSUFFICIENT_BALANCE
  • 403SERVICE_NOT_ACTIVE, PRODUCT_NOT_IN_CATALOGUE, MONTHLY_CAP_REACHED, or a scope or account refusal
  • 404PACKAGE_NOT_FOUND (sandbox)
  • 409REFERENCE_IN_USE, PACKAGE_NOT_AVAILABLE, PRICE_ON_HOLD or an Idempotency-Key conflict
Response fields
idExists from the first answer; follow it to issued or failed.string
referencestring | null
environmentstring: live, test
statusstring: processing, issued, installed, used_up, expired, closed, cancelled, failed
packageobject
priceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
iccidstring | null
installobject | null
allowanceMbnumber | null
usageobject
topupSupportedboolean | null
expiresAtstring | null
failurestring | null
refundedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
createdAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/esims" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"packageId":4521,"reference":"ORDER-1001"}'
GET/esims/{id}esims:read

One eSIM — its state, install data and, where the operator reports it, usage

Scope esims:read. usage.reported is false where the operator does not report consumption: only the allowance is given then, never an estimate.

Request

FieldInType
idpathstringrequired

Responses

  • 200The eSIM.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idExists from the first answer; follow it to issued or failed.string
referencestring | null
environmentstring: live, test
statusstring: processing, issued, installed, used_up, expired, closed, cancelled, failed
packageobject
priceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
iccidstring | null
installobject | null
allowanceMbnumber | null
usageobject
topupSupportedboolean | null
expiresAtstring | null
failurestring | null
refundedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
createdAtstring
Request
curl "https://miragetel.com/api/v1/partner/esims/<id>" \
  -H "X-Api-Key: mtp_test_…"
GET/esims/{id}/qr.pngesims:read

The activation QR code, as a PNG

Scope esims:read. Generated here from the activation code; never by a third party.

Request

FieldInType
idpathstringrequired

Responses

  • 200The QR code.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409NOT_ISSUED
Request
curl "https://miragetel.com/api/v1/partner/esims/<id>/qr.png" \
  -H "X-Api-Key: mtp_test_…"
GET/esims/{id}/topup-optionsesims:read

What can be added to this eSIM, at your price

Scope esims:read.

Request

FieldInType
idpathstringrequired

Responses

  • 200The options.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409NOT_ISSUED, TOPUP_NOT_SUPPORTED or TOPUP_WINDOW_CLOSED
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/esims/<id>/topup-options" \
  -H "X-Api-Key: mtp_test_…"
POST/esims/{id}/topupsesims:writeIdempotency-Key

Add data to an eSIM, from your balance

Scope esims:write. Same eSIM, no reinstall. esim.topup.completed (or esim.topup.failed, nothing charged) follows.

Request

FieldInType
idpathstringrequired
packageCodebodystringrequired

Responses

  • 201The top-up.
  • 400INVALID_TOPUP_OPTION or IDEMPOTENCY_KEY_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 402INSUFFICIENT_FUNDS
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409NOT_ISSUED, TOPUP_NOT_SUPPORTED, TOPUP_WINDOW_CLOSED, PRICE_ON_HOLD or ESIM_TEMPORARILY_UNAVAILABLE
  • 503SUPPLY_TEMPORARILY_UNAVAILABLE
Response fields
idstring
esimIdstring
environmentstring
packageCodestring
priceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
statusstring: processing, completed, under_review
Request
curl -X POST "https://miragetel.com/api/v1/partner/esims/<id>/topups" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"packageCode":"<packageCode>"}'
POST/esims/{id}/cancelesims:write

Cancel an eSIM — refunded to your balance where the operator refunds it

Scope esims:write. refundedMinor is what came back to your balance; esim.cancelled follows.

Request

FieldInType
idpathstringrequired

Responses

  • 200The eSIM
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409CANCEL_REJECTED or NOT_ISSUED
Response fields
idExists from the first answer; follow it to issued or failed.string
referencestring | null
environmentstring: live, test
statusstring: processing, issued, installed, used_up, expired, closed, cancelled, failed
packageobject
priceMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
iccidstring | null
installobject | null
allowanceMbnumber | null
usageobject
topupSupportedboolean | null
expiresAtstring | null
failurestring | null
refundedMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
createdAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/esims/<id>/cancel" \
  -H "X-Api-Key: mtp_test_…"

Numbers and end users

Local numbers, their registration, and the people who use them.

GET/numbers/areasnumbers:read

The areas of a country, at your price

Scope numbers:read. Monthly and setup price of one number in each area, and whether the country registers the user of a number before it works.

Request

FieldInType
countryquerystringrequired
qquerystring
limitqueryinteger
offsetqueryinteger

Responses

  • 200The areas.
  • 400INVALID_COUNTRY
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404COUNTRY_NOT_SOLD
Response fields
countrystring
currencystring
totalinteger
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/numbers/areas?country=DE" \
  -H "X-Api-Key: mtp_test_…"
GET/numbersnumbers:read

Your numbers, newest first

Scope numbers:read.

Request

FieldInType
statusquerystring
referencequerystring
limitqueryinteger

Responses

  • 200The numbers.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/numbers" \
  -H "X-Api-Key: mtp_test_…"
POST/numbersnumbers:writeIdempotency-Key

Buy a phone number for your customer, from your balance

Scope numbers:write. Needs the numbers service switched on for your account and your company’s acceptable use policy. The first month (and a setup fee where the area has one) is paid at once. In a country that registers the user, the number waits for its registration (number.registration.required, then POST …/registration). endUserId names whose line it is; reference is your own id. Sandbox: a +999 number at once, play money.

Request

FieldInType
countrybodystringrequired
areaIdbodystringrequired
referencebodystring
endUserIdbodystring

Responses

  • 201The number.
  • 400INVALID_COUNTRY, INVALID_AREA, INVALID_REFERENCE or IDEMPOTENCY_KEY_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 402INSUFFICIENT_FUNDS
  • 403SERVICE_NOT_ACTIVE, AUP_REQUIRED, NUMBER_COUNTRY_SANCTIONED, or a scope or account refusal
  • 404COUNTRY_NOT_SOLD or END_USER_NOT_FOUND
  • 409REFERENCE_IN_USE, AREA_NOT_AVAILABLE or an Idempotency-Key conflict
  • 502NUMBER_ORDER_FAILED — nothing was charged
Response fields
idstring
referencestring | null
environmentstring: live, test
e164string | null
countrystring
statusstring
endUserobject | null
monthlyMinorobject
setupMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
registrationobject
routingobject
currentPeriodEndstring | null
autoRenewboolean
cancelAtPeriodEndboolean
createdAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/numbers" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"country":"DE","areaId":"<areaId>","reference":"ORDER-1001"}'
GET/numbers/{id}numbers:read

One number

Scope numbers:read.

Request

FieldInType
idpathstringrequired

Responses

  • 200The number.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
referencestring | null
environmentstring: live, test
e164string | null
countrystring
statusstring
endUserobject | null
monthlyMinorobject
setupMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
registrationobject
routingobject
currentPeriodEndstring | null
autoRenewboolean
cancelAtPeriodEndboolean
createdAtstring
Request
curl "https://miragetel.com/api/v1/partner/numbers/<id>" \
  -H "X-Api-Key: mtp_test_…"
PATCH/numbers/{id}numbers:write

Where calls to the number ring

Scope numbers:write. routing.to: trunk (with trunkId) or none.

Request

FieldInType
idpathstringrequired
routingbodyobjectrequired

Responses

  • 200The number.
  • 400INVALID_ROUTING
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
referencestring | null
environmentstring: live, test
e164string | null
countrystring
statusstring
endUserobject | null
monthlyMinorobject
setupMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
registrationobject
routingobject
currentPeriodEndstring | null
autoRenewboolean
cancelAtPeriodEndboolean
createdAtstring
Request
curl -X PATCH "https://miragetel.com/api/v1/partner/numbers/<id>" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"routing":{}}'
DELETE/numbers/{id}numbers:write

Cancel a number at the end of its paid month

Scope numbers:write. number.cancelled follows.

Request

FieldInType
idpathstringrequired

Responses

  • 200The number.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409NOT_CANCELLABLE
Response fields
idstring
referencestring | null
environmentstring: live, test
e164string | null
countrystring
statusstring
endUserobject | null
monthlyMinorobject
setupMinorAn amount in minor units (cents), stored as PostgreSQL BIGINT. Never a float, never a decimal string, never scaled at the boundary. 1999 means $19.99. Signed where the field represents a movement (ledger entries, adjustments); non-negative where it represents a balance.integer (cents)
currencystring
registrationobject
routingobject
currentPeriodEndstring | null
autoRenewboolean
cancelAtPeriodEndboolean
createdAtstring
Request
curl -X DELETE "https://miragetel.com/api/v1/partner/numbers/<id>" \
  -H "X-Api-Key: mtp_test_…"
GET/numbers/{id}/registrationnumbers:read

What the country asks to register the number’s user

Scope numbers:read. The fields and documents the operator asks for.

Request

FieldInType
idpathstringrequired

Responses

  • 200The form.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Request
curl "https://miragetel.com/api/v1/partner/numbers/<id>/registration" \
  -H "X-Api-Key: mtp_test_…"
POST/numbers/{id}/registrationnumbers:write

File the registration

Scope numbers:write. identityType, identity and address fields as the form asks — filled from the end user you gave the number when you leave them out — and documents (base64). The verdict arrives as number.registration.approved or …rejected (with what to correct).

Request

FieldInType
idpathstringrequired
identityTypebodystring: personal, business
identitybodyobject
addressbodyobject
serviceDescriptionbodystring
documentsbodyarray of object

Responses

  • 200Filed.
  • 400A field or a document is missing or invalid
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
  • 409NO_REGISTRATION or LIVE_ONLY
Request
curl -X POST "https://miragetel.com/api/v1/partner/numbers/<id>/registration" \
  -H "X-Api-Key: mtp_test_…"
GET/end-usersend_users:read

Your end users

Scope end_users:read. What a registration needs is held encrypted and never read back in full.

Request

FieldInType
referencequerystring
limitqueryinteger

Responses

  • 200The end users.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/end-users" \
  -H "X-Api-Key: mtp_test_…"
POST/end-usersend_users:writeIdempotency-Key

Record an end user — the identity a country registers a number to

Scope end_users:write. Only what a registration asks for; stored encrypted, filed with the operator, read by nobody else.

Request

FieldInType
identityTypebodystring: personal, businessrequired
namebodystringrequired
countrybodystring
referencebodystring
identitybodyobject
addressbodyobject

Responses

  • 201The end user.
  • 400INVALID_IDENTITY_TYPE, INVALID_NAME, INVALID_COUNTRY or INVALID_REFERENCE
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 409REFERENCE_IN_USE
Response fields
idstring
referencestring | null
identityTypestring: personal, business
namestring
countrystring | null
fieldsHeldThe names of the fields we hold — never their values.object
createdAtstring
updatedAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/end-users" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"identityType":"personal","name":"Office PBX","country":"DE","reference":"ORDER-1001"}'
GET/end-users/{id}end_users:read

One end user

Scope end_users:read.

Request

FieldInType
idpathstringrequired

Responses

  • 200The end user.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404END_USER_NOT_FOUND
Response fields
idstring
referencestring | null
identityTypestring: personal, business
namestring
countrystring | null
fieldsHeldThe names of the fields we hold — never their values.object
createdAtstring
updatedAtstring
Request
curl "https://miragetel.com/api/v1/partner/end-users/<id>" \
  -H "X-Api-Key: mtp_test_…"
PATCH/end-users/{id}end_users:write

Correct an end user

Scope end_users:write. end_user.updated follows.

Request

FieldInType
idpathstringrequired
namebodystring
identitybodyobject
addressbodyobject

Responses

  • 200The end user.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404END_USER_NOT_FOUND
Response fields
idstring
referencestring | null
identityTypestring: personal, business
namestring
countrystring | null
fieldsHeldThe names of the fields we hold — never their values.object
createdAtstring
updatedAtstring
Request
curl -X PATCH "https://miragetel.com/api/v1/partner/end-users/<id>" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"Office PBX"}'
DELETE/end-users/{id}end_users:write

Delete an end user (its fields are erased)

Scope end_users:write. Refused while the end user holds a number.

Request

FieldInType
idpathstringrequired

Responses

  • 200Deleted.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404END_USER_NOT_FOUND
  • 409END_USER_HAS_NUMBERS
Response fields
deletedboolean
Request
curl -X DELETE "https://miragetel.com/api/v1/partner/end-users/<id>" \
  -H "X-Api-Key: mtp_test_…"

SIP trunks, calls and texts

Connect phone systems, read every call, send and receive texts.

GET/trunkstrunks:read

Your SIP trunks, with today’s use

Scope trunks:read.

Request

No parameters.

Responses

  • 200The trunks.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
connectionobject
Request
curl "https://miragetel.com/api/v1/partner/trunks" \
  -H "X-Api-Key: mtp_test_…"
POST/trunkstrunks:writeIdempotency-Key

Connect a phone system — the password is shown once

Scope trunks:write. Needs outbound calling switched on for your account and acceptAup: true with the current aupVersion. Minutes are paid from your balance at your rate card (GET /partner/rates/voice); maxChannels and dailyLimitMinor cap it.

Request

FieldInType
namebodystring
maxChannelsbodyinteger
dailyLimitMinorbodyobject
cliModebodystring: fixed, random
cliNumberIdbodystring
acceptAupbodybooleanrequired
aupVersionbodystringrequired

Responses

  • 201The trunk and its password.
  • 400AUP_NOT_ACCEPTED, INVALID_NAME, INVALID_CHANNELS, INVALID_DAILY_LIMIT or CLI_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403SERVICE_NOT_ACTIVE, or a scope, account or compliance refusal
  • 409NO_NUMBER, NO_CREDIT, AUP_VERSION_CHANGED or an Idempotency-Key conflict
Response fields
trunkobject
sipPasswordstring
shownOnceboolean
environmentstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/trunks" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Office PBX","acceptAup":true,"aupVersion":"<aupVersion>"}'
PATCH/trunks/{id}trunks:write

Change a trunk’s name, lines, daily cap, caller ID or state

Scope trunks:write.

Request

FieldInType
idpathstringrequired
namebodystring
maxChannelsbodyinteger
dailyLimitMinorbodyobject
cliModebodystring
cliNumberIdbodystring
statusbodystring: active, disabled

Responses

  • 200The trunk.
  • 400An invalid field
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Request
curl -X PATCH "https://miragetel.com/api/v1/partner/trunks/<id>" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"Office PBX"}'
DELETE/trunks/{id}trunks:write

Delete a trunk

Scope trunks:write. Its numbers stop ringing it.

Request

FieldInType
idpathstringrequired

Responses

  • 200Deleted.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Request
curl -X DELETE "https://miragetel.com/api/v1/partner/trunks/<id>" \
  -H "X-Api-Key: mtp_test_…"
GET/trunks/{id}/statustrunks:read

Whether the phone system is registered, and today’s calls

Scope trunks:read.

Request

FieldInType
idpathstringrequired

Responses

  • 200The status.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Request
curl "https://miragetel.com/api/v1/partner/trunks/<id>/status" \
  -H "X-Api-Key: mtp_test_…"
POST/trunks/{id}/rotate-passwordtrunks:write

A new SIP password — shown once

Scope trunks:write. The old one stops working at once.

Request

FieldInType
idpathstringrequired

Responses

  • 200The new password.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Request
curl -X POST "https://miragetel.com/api/v1/partner/trunks/<id>/rotate-password" \
  -H "X-Api-Key: mtp_test_…"
GET/callscalls:read

Calls on your numbers and trunks, with what each was charged

Scope calls:read. Newest first; before pages back.

Request

FieldInType
limitqueryinteger
beforequerystring
filterquerystring: all, attempts, charged

Responses

  • 200The calls.
  • 400INVALID_FILTER or INVALID_BEFORE
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
monthobject
Request
curl "https://miragetel.com/api/v1/partner/calls" \
  -H "X-Api-Key: mtp_test_…"
GET/textssms:read

Texts sent and received on your numbers

Scope sms:read.

Request

FieldInType
numberIdquerystring
limitqueryinteger

Responses

  • 200The texts.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
environmentstring
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/texts" \
  -H "X-Api-Key: mtp_test_…"
POST/textssms:writeIdempotency-Key

Send a text from one of your numbers

Scope sms:write. Needs outbound texts switched on for your account. Charged per part at your SMS rate card; text.status.changed follows the operator’s verdict.

Request

FieldInType
numberIdbodystringrequired
tobodystringrequired
textbodystringrequired

Responses

  • 201Sent.
  • 400INVALID_MESSAGE or INVALID_NUMBER
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 402INSUFFICIENT_FUNDS
  • 403SERVICE_NOT_ACTIVE, DESTINATION_NOT_ALLOWED or DESTINATION_SANCTIONED
  • 409NO_ACTIVE_NUMBER, SMS_SENDING_NOT_OPEN or SMS_DESTINATION_NOT_PRICED
Request
curl -X POST "https://miragetel.com/api/v1/partner/texts" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"numberId":"<numberId>","to":"+4915112345678","text":"Your code is 4321"}'

Rate cards

Your own price for everything, as JSON or CSV.

GET/rates/esimrates:read

Your price for every eSIM package

Scope rates:read. Your price from your partner agreement, in whole cents — the price a purchase charges. available is false while a package cannot be bought this minute (for example out of stock), with the reason in hold. format=csv downloads the same list.

Request

FieldInType
countryquerystring
formatquerystring: json, csv

Responses

  • 200The packages.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
currencystring
Request
curl "https://miragetel.com/api/v1/partner/rates/esim" \
  -H "X-Api-Key: mtp_test_…"
GET/rates/numbersrates:read

Your from-price for a phone number in every country

Scope rates:read. The cheapest area's monthly and setup price; whether the country registers the user of a number.

Request

FieldInType
formatquerystring: json, csv

Responses

  • 200One row per country.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
currencystring
Request
curl "https://miragetel.com/api/v1/partner/rates/numbers" \
  -H "X-Api-Key: mtp_test_…"
GET/rates/voicerates:read

Your per-minute price to every destination (SIP trunk calls)

Scope rates:read. Billed 60/60. q filters by destination name or prefix; paged with limit/offset.

Request

FieldInType
qquerystring
limitqueryinteger
offsetqueryinteger
formatquerystring: json, csv

Responses

  • 200A page of destinations.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
totalinteger
limitinteger
offsetinteger
currencystring
reasonstring | null
Request
curl "https://miragetel.com/api/v1/partner/rates/voice" \
  -H "X-Api-Key: mtp_test_…"
GET/rates/smsrates:read

Your price for one part of an outbound text, per destination

Scope rates:read. A destination we cannot price yet is listed as not open — never at a guess.

Request

FieldInType
formatquerystring: json, csv

Responses

  • 200One row per destination prefix.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
currencystring
Request
curl "https://miragetel.com/api/v1/partner/rates/sms" \
  -H "X-Api-Key: mtp_test_…"

Webhooks and events

Be told when something happens — signed — or read the log.

GET/webhookswebhooks:manage

Your webhooks in this environment

Scope webhooks:manage. Up to 5 per environment.

Request

No parameters.

Responses

  • 200The webhooks and the event types they can ask for.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
Response fields
dataarray of object
limitinteger
signatureHeaderstring
eventsarray of string
Request
curl "https://miragetel.com/api/v1/partner/webhooks" \
  -H "X-Api-Key: mtp_test_…"
POST/webhookswebhooks:manageIdempotency-Key

Add a webhook — the signing secret is shown once

Scope webhooks:manage. A public https address (resolved now and before every delivery; private addresses are refused). events: exact types or families (esim.*), or *. Each delivery is signed with HMAC-SHA256 over "<X-MirageTel-Timestamp>.<body>" in X-MirageTel-Signature and retried for 24 hours.

Request

FieldInType
urlbodystringrequired
eventsbodyarray of string
descriptionbodystring

Responses

  • 201Created
  • 400INVALID_WEBHOOK_URL, WEBHOOK_NOT_PUBLIC, WEBHOOK_UNRESOLVED, UNKNOWN_EVENT or IDEMPOTENCY_KEY_REQUIRED
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 409TOO_MANY_WEBHOOKS or an Idempotency-Key conflict
Response fields
idstring
environmentstring: live, test
urlstring
eventsarray of string
descriptionstring | null
activeboolean
failuresInRowinteger
lastSuccessAtstring | null
lastFailureAtstring | null
lastErrorstring | null
disabledReasonstring | null
secretOnly when the webhook is created or its secret rotated.string
createdAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/webhooks" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Idempotency-Key: <unique id>" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.example/miragetel","events":["esim.*","balance.low"]}'
PATCH/webhooks/{id}webhooks:manage

Change a webhook's address, events or state

Request

FieldInType
idpathstringrequired
urlbodystring
eventsbodyarray of string
descriptionbodystring
activebodyboolean

Responses

  • 200The webhook.
  • 400Invalid address or event
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
environmentstring: live, test
urlstring
eventsarray of string
descriptionstring | null
activeboolean
failuresInRowinteger
lastSuccessAtstring | null
lastFailureAtstring | null
lastErrorstring | null
disabledReasonstring | null
secretOnly when the webhook is created or its secret rotated.string
createdAtstring
Request
curl -X PATCH "https://miragetel.com/api/v1/partner/webhooks/<id>" \
  -H "X-Api-Key: mtp_test_…" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.example/miragetel","events":["esim.*","balance.low"]}'
DELETE/webhooks/{id}webhooks:manage

Delete a webhook; its pending deliveries are cancelled

Request

FieldInType
idpathstringrequired

Responses

  • 200Deleted.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
deletedboolean
Request
curl -X DELETE "https://miragetel.com/api/v1/partner/webhooks/<id>" \
  -H "X-Api-Key: mtp_test_…"
POST/webhooks/{id}/rotate-secretwebhooks:manage

A new signing secret, shown once; the old one stops at once

Request

FieldInType
idpathstringrequired

Responses

  • 200The webhook with its new secret.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
environmentstring: live, test
urlstring
eventsarray of string
descriptionstring | null
activeboolean
failuresInRowinteger
lastSuccessAtstring | null
lastFailureAtstring | null
lastErrorstring | null
disabledReasonstring | null
secretOnly when the webhook is created or its secret rotated.string
createdAtstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/webhooks/<id>/rotate-secret" \
  -H "X-Api-Key: mtp_test_…"
POST/webhooks/{id}/testwebhooks:manage

Send a signed webhook.test event now, and say what the address answered

Request

FieldInType
idpathstringrequired

Responses

  • 200The outcome.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
okboolean
statusinteger | null
errorstring | null
eventIdstring
deliveryIdstring
Request
curl -X POST "https://miragetel.com/api/v1/partner/webhooks/<id>/test" \
  -H "X-Api-Key: mtp_test_…"
GET/webhooks/{id}/deliverieswebhooks:manage

The latest deliveries to one webhook

Request

FieldInType
idpathstringrequired
limitqueryinteger

Responses

  • 200Deliveries
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
dataarray of object
Request
curl "https://miragetel.com/api/v1/partner/webhooks/<id>/deliveries" \
  -H "X-Api-Key: mtp_test_…"
GET/eventsevents:read

Every event of this environment, oldest first from a cursor

Scope events:read. Kept 90 days. after is the id of the last event you have; type an exact type or family.*.

Request

FieldInType
afterquerystring
typequerystring
limitqueryinteger
orderoldest (default) reads after a cursor; newest returns the latest events, newest first, and takes no cursorquerystring: oldest, newest

Responses

  • 200A page of events.
  • 400INVALID_CURSOR
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404CURSOR_NOT_FOUND
Response fields
dataarray of object
hasMoreboolean
nextAfterstring | null
Request
curl "https://miragetel.com/api/v1/partner/events" \
  -H "X-Api-Key: mtp_test_…"
GET/events/{id}events:read

One event

Request

FieldInType
idpathstringrequired

Responses

  • 200The event.
  • 401API_KEY_INVALID, or no key and no session (UNAUTHORIZED).
  • 403INSUFFICIENT_SCOPE, PANEL_ONLY, PARTNER_ONLY, PARTNER_SUSPENDED (reads only) or PARTNER_INACTIVE.
  • 404NOT_FOUND
Response fields
idstring
typestring
environmentstring: live, test
objectobject | null
dataobject
createdAtstring
Request
curl "https://miragetel.com/api/v1/partner/events/<id>" \
  -H "X-Api-Key: mtp_test_…"

Developer questions

How do I get a key?

Once your partner account is active, an administrator issues keys in the partner panel under Developers. A developer of your team can issue sandbox keys.

What is the sandbox?

A second environment with its own keys (mtp_test_…), its own play-money balance, its own objects and its own events. Nothing in it reaches an operator or your real balance.

Can a request be charged twice?

No, if you send an Idempotency-Key: a retry with the same key and the same body gets the first answer back. Every request that creates or pays requires one.

How do I know a webhook is from you?

Check X-MirageTel-Signature: HMAC-SHA256 with your webhook secret over the X-MirageTel-Timestamp, a dot and the raw body. Refuse an old timestamp.

Is there an OpenAPI file?

Yes — /partners/developers/openapi.json, the same contract this page is generated from. Point your client generator at it.

Own Signal

Keys open with your account.

Apply, we review your company, and your sandbox is ready the day we activate you.