Base URL
https://terudo.com/api/partner/v1
Authentication
Send your key in the Authorization header. Secret keys (sk_…) stay on your server and see your net prices. Publishable keys (pk_…) go in your pages for the Elements and only see public prices. Test keys (…_test_…) create sandbox orders: no payment, no real eSIM, nothing billed; the pay page offers a “simulate the payment” button.
curl https://terudo.com/api/partner/v1/me \
-H "Authorization: Bearer sk_test_…"
Two models
Commission: Terudo sells to the traveller, who pays on our hosted page and accepts our terms; you earn a commission. Net: you buy from your prepaid credit and invoice your client yourself. You choose on every order.
Plan ids
Fixed plans: DESTINATION-GB, as in MA-10. Daily plans: DESTINATION-DAYgb-nD, as in MA-DAY2-8D (2 GB a day for 8 days). The trip quote returns the right id for the dates you give.
Lists return { object: "list", data: [...] }; /orders adds has_more and takes starting_after. Amounts are integers in euro cents, incl. VAT for client prices and excl. VAT for net prices and commissions. Dates are ISO 8601, UTC.
Keys and webhooks are managed in your partner portal, Developers tab, once we have opened the API for your account.
Catalogue
Two plan families. Fixed plans from the grid (“MA-10”: Morocco, 10 GB, 30 days). Daily plans, built on demand for a number of days (“MA-DAY2-8D”: Morocco, 2 GB a day for 8 days, then reduced speed). A plan id is passed as is when ordering.
GET /destinations Destinations secret key
The destinations of the catalogue, with their fixed plan ids and whether daily plans exist.
Response{ "object": "list", "data": [ { "code": "MA", "name": "Maroc", "name_en": "Morocco", "fixed_plans": ["MA-3", "MA-10"], "daily_plans": true }, … ] }
GET /plans Plans secret key
Plans at your rate: recommended public price, default client price, net price and commission. With destination and days, daily plans of that length are added.
destination string- ISO code (MA) or region (EU-35). Omitted: the whole grid.
days integer 1–30- Length of the daily plans to add.
Response{ "object": "list", "data": [ { "id": "MA-10", "object": "plan", "kind": "fixed", "destination": "MA", "name": "Maroc", "gb": 10, "days": 30, "public_price_cents": 2999, "client_price_cents": 2849, "net_cents": 1780, "commission_cents": 594 }, { "id": "MA-DAY2-7D", "kind": "daily", "gb": 2, "days": 7, "speed_after_quota": "1 Mbit/s", … } ] }
GET /plans/{id} One plan secret key
One plan by id, fixed or daily.
POST /quotes Quote for a trip secret key
Give the destination and dates: the answer lists the plans that cover the stay and recommends one, the cheapest that covers it all, with a buffer day for a late flight. Nothing is created.
destination string · required- Destination code.
start_date date · required- Arrival, YYYY-MM-DD.
end_date date · required- Departure, YYYY-MM-DD. 60 days at most.
profile light | normal | heavy- Estimated use: 0.5, 1 or 2 GB a day. Default normal.
buffer_days integer 0–3- Days added to the covered length. Default 1.
Request{ "destination": "MA", "start_date": "2026-12-03", "end_date": "2026-12-09", "profile": "normal" }
Response{ "object": "quote", "trip_days": 7, "covered_days": 8, "needed_gb": 7,
"options": [
{ "id": "MA-DAY1-8D", "kind": "daily", "gb": 1, "days": 8, "public_price_cents": 2099, "net_cents": 1246, "covers_trip": true, "recommended": true, "reason": "1 Go par jour pendant 8 jours, puis débit réduit" },
{ "id": "MA-10", "kind": "fixed", "gb": 10, "days": 30, "public_price_cents": 2999, "covers_trip": true, "recommended": false, "reason": "10 Go sur 30 jours, couvre 7 Go estimés" },
…
] }
GET /coverage/{destination} Does the traveller’s plan already cover it? any key
Which main French mobile plans already include the destination, from our verified records. With brand and plan, checks one plan. To tell the client the truth before selling.
brand string- The traveller’s plan brand (Free, Sosh, …).
plan string- Plan name.
Response{ "object": "coverage", "destination": "MA", "french_plans_including": [], "checked_plan": null, "advice": "Aucun forfait français principal n'inclut cette destination : une eSIM est le bon réflexe." }
GET /compatibility Does the phone take an eSIM? any key
From the model as the traveller gives it: yes, depends (some versions only, the note says which), no or unknown (model not in our list, the note describes the brand’s range). The two checks to do on the phone always come along: *#06# for the EID, phone not carrier-locked.
device string · required- Model: iPhone 13 mini, Galaxy S23, Pixel 7a…
Response{ "object": "compatibility", "device": "iPhone 13 mini", "brand": "Apple", "compatible": "yes", "note": "Sauf modèle acheté en Chine continentale…", "checks": ["Composer *#06# : si un numéro EID s'affiche, le téléphone prend une eSIM.", "Le téléphone doit être désimlocké…"] }
Orders
Two models, chosen on every order. Commission: Terudo sells to the client, who pays on our page (checkout_url) and accepts our terms; you earn the commission. Net: you buy at the net price from your prepaid credit, the eSIM is delivered at once and you invoice your client yourself. An order with a reference is idempotent: the same reference returns the same order.
POST /orders Create an order secret key
Creates the order. In commission mode, returns a checkout_url to show the client (or notify_client to have us mail the link). In net mode, debits the credit and starts delivery, now or at deliver_at.
plan string · required- Plan id, fixed or daily.
kind commission | net- Default commission.
client.email string · required- The traveller. The eSIM goes to this address.
client.locale fr | en- Language of the emails and the pay page.
reference string ≤ 120- Your id (file, booking). Unique per account, idempotency key: the same reference returns the same order (200). An Idempotency-Key header stands in for it when the body has none.
trip.start_date, trip.end_date date- Trip dates. Refused if the plan is too short. Drives reminders.
discount_percent integer 0–15- Commission only. Client discount taken from your commission. Default 5.
return_url https URL- Where the pay page sends the client once paid.
notify_client boolean- Commission: we email the payment link. Default false.
deliver_at datetime ISO 8601- Deferred delivery, 90 days at most. Or days_before_trip (integer) with trip. A daily plan must be installed within 30 days: sold more than 25 days before the trip, it is delivered 7 days before departure unless told otherwise.
auto_topup_max integer 0–10- Net only: dynamic plan. When data runs low, the same plan is added from your credit, at most this many times.
metadata object ≤ 20 clés- Your data, returned as is.
Request{ "plan": "MA-DAY2-8D", "kind": "commission", "reference": "visa-48213",
"client": { "email": "[email protected]", "locale": "fr" },
"trip": { "start_date": "2026-12-03", "end_date": "2026-12-09" },
"return_url": "https://partner.example/trips/48213", "metadata": { "trip_id": "48213" } }
Response{
"id": "6b1f…",
"object": "order",
"reference": "visa-48213",
"mode": "live",
"kind": "commission",
"status": "pending",
"plan": { "id": "MA-DAY2-8D", "kind": "daily", "destination": "MA", "name": "Maroc", "gb": 2, "days": 8 },
"client": { "email": "[email protected]", "locale": "fr" },
"trip": { "start_date": "2026-12-03", "end_date": "2026-12-09" },
"price_cents": 2944, "currency": "EUR", "discount_percent": 5,
"net_cents": 1840, "commission_cents": 613,
"checkout_url": "https://terudo.com/pay/…/",
"return_url": "https://partner.example/trips/48213",
"deliver_at": null, "auto_topup_max": 0,
"metadata": { "trip_id": "48213" },
"created_at": "2026-11-08T10:12:00Z", "paid_at": null, "esim": null
}
GET /orders List secret key
Your orders, newest first, 50 a page (starting_after = last id). Filters: reference, status, email.
GET /orders/{id} One order secret key
By Terudo id or by your reference. Statuses: pending, paid, ordered, delivered, failed, refunded, cancelled, expired. The esim object appears once delivered.
POST /orders/{id}/cancel Cancel secret key
An unpaid link is cancelled. A paid order is refunded while the eSIM was never installed: to your credit in net mode, to the client’s card in commission mode.
reason string- Reason, kept in the log.
POST /orders/{id}/remind Remind the client secret key
Mails the payment link again (commission, two reminders at most, 24 h apart).
eSIMs
An eSIM’s id is that of its order’s esim object; it is also the token of the client’s “My eSIM” page (page_url), which you may show in your own space.
GET /esims/{id} One eSIM secret key
Status, installation, usage, activation code, iOS and Android install links, QR code.
Response{
"id": "k8Zs…", // esim id, also the token of the client's page
"object": "esim",
"status": "active", "profile_status": "enabled",
"installed_at": "2026-12-02T18:04:11Z", "expires_at": "2026-12-11T00:00:00Z",
"used_bytes": 1431655765, "total_bytes": 17179869184,
"iccid": "8944…", "activation_code": "LPA:1$…$…", "smdp_address": "…", "matching_id": "…",
"ios_install_url": "https://esimsetup.apple.com/…", "android_install_url": "https://esimsetup.android.com/…",
"page_url": "https://terudo.com/esim/k8Zs…/", "qr_url": "https://terudo.com/api/esims/k8Zs…/qr/",
"topups": 0
}
GET /esims/{id}/usage Usage secret key
Used and total data, refreshed from the supplier at most every 10 minutes.
GET /esims/{id}/topups Available top-ups secret key
The same plan again and, for a daily plan, extra days (1, 3, 7), on the same eSIM when the supplier allows it.
POST /esims/{id}/topups Top up secret key
Net: the top-up is taken from the credit and added to the eSIM. Commission: a payment link opens for the client and comes back as a new order.
plan string- A plan of the same destination. Default: the eSIM’s.
POST /esims/{id}/resend Resend the instructions secret key
Mails the install e-mail (QR code, install link) again to the traveller’s address on the order: lost e-mail, new phone. Delivered eSIMs only, three times a day at most.
POST /esims/{id}/suspend Suspend secret key
Cuts the data of an eSIM bought at the net price (traveller gone, lost device). Nothing is refunded, the plan keeps running.
POST /esims/{id}/resume Resume secret key
Restores the data.
Webhooks
We call your https address at every step. Each call carries Terudo-Signature: t=<timestamp>,v1=<hex HMAC-SHA256 of "t.body" with the endpoint secret>. Verify the signature and reject a timestamp older than 5 minutes. Failures are retried after 1, 5, 30, 120 and 720 minutes; 25 failures in a row switch the endpoint off, to be re-enabled from the portal or the API. Body: { id, type, created_at, mode, data: { order } }.
GET /webhooks List secret key
Your endpoints in the key’s mode, and the list of events.
POST /webhooks Create secret key
public https url (port 443) and events (empty: all). The secret is returned.
Request{ "url": "https://partner.example/hooks/terudo", "events": ["order.paid", "order.delivered", "esim.installed", "esim.low_data"] }
Response{ "id": 3, "object": "webhook_endpoint", "url": "https://partner.example/hooks/terudo", "mode": "live", "events": [ … ], "secret": "whsec_…" }
PATCH /webhooks/{id} Update secret key
url, events, enabled.
DELETE /webhooks/{id} Delete secret key
POST /webhooks/{id}/test Send a test secret key
A signed test event, right away.
GET /webhooks/{id}/deliveries Deliveries secret key
The last 100 deliveries, with their state and your server’s answer.
POST /webhooks/{id}/deliveries/{delivery_id}/resend Resend secret key
Elements: the publishable key
These routes serve the Elements in your pages, with a pk_… key and CORS open to the key’s sites. Never a net price. An element_session created by your server with the secret key unlocks the client discount, the member rate, and a prefilled trip and reference.
POST /element_sessions Session for a page secret key
Returns client_token, valid 2 hours, to pass to the Elements (session option).
discount_percent integer 0–15- Client discount on this page.
client_email, reference, return_url, locale, metadata - As for an order.
trip object- destination, start_date, end_date, profile.
GET /public/destinations Destinations publishable key
GET /public/plans Plans at the public price publishable key
?destination, ?days, ?session.
POST /public/quotes Quote publishable key
As /quotes, at the public price.
POST /public/checkout Hosted checkout publishable key
Creates a commission order and returns checkout_url. 30 an hour per IP address.
plan string · requiredemail string · required- Unless the session carries it.
return_url, locale, trip, session - return_url is kept only when its origin is among the sites listed on the publishable key, or when it comes from the signed session. A key with no site list takes no return address from the page.
GET /public/esims/{id} eSIM page publishable key
The “My eSIM” page data, without the activation code.
MCP server for AI assistants
Your AI assistant (Claude, ChatGPT, any MCP client) can quote, sell and follow eSIMs for you. The MCP server takes the same keys as the API, works in the sandbox with a test key, and each tool calls one route of this reference, with the same prices and errors. Streamable HTTP transport.
claude mcp add --transport http terudo https://terudo.com/api/partner/v1/mcp/ --header "Authorization: Bearer sk_test_…"
Other clients: MCP server over HTTP at this address, with the header Authorization: Bearer and your key. https://terudo.com/api/partner/v1/mcp/
Tools with a secret key
- Account and catalogue
account, destinations, plans_list, plan_show, quote_trip, coverage_check, compatibility_check- Orders
orders_list, order_show, order_create, order_cancel, order_remind- eSIMs
esim_show, esim_usage, esim_topup_options, esim_topup, esim_resend, esim_suspend, esim_resume- Webhooks
webhooks_list, webhook_show, webhook_create, webhook_update, webhook_delete, webhook_test, webhook_deliveries, webhook_resend- Statements
statements_list, statement_show
With a publishable key (pk_…), the assistant sells for you without ever seeing a net price: public prices, the checks before the sale, and a payment link on your checkout page. Tools: destinations, plans_list, quote_trip, coverage_check, compatibility_check, checkout, esim_page.
To try it without an account, use our public demo key: real catalogue, quotes and checks, no payment link.
claude mcp add --transport http terudo https://terudo.com/api/partner/v1/mcp/ --header "Authorization: Bearer pk_test_terudo_demo_public"
Webhook events
order.paid- The client paid (commission), or the credit was debited (net).
order.delivered- The eSIM was sent to the client; the esim object is filled.
order.failed- The supplier did not deliver; we step in.
order.refunded- Refunded, by you or by us.
order.cancelled- Payment link cancelled.
esim.installed- The profile is installed on a phone.
esim.low_data- A quarter of the data or less.
esim.used_up- Out of data.
esim.expiring- Validity ends soon.
esim.expired- Validity over.
esim.deleted- The client removed the profile from the phone.
esim.suspended- Data cut.
esim.resumed- Data restored.
topup.delivered- A top-up was added to the eSIM.
Errors
Every error is { "error": { "code", "message" } }. Messages are in French; codes are stable.
unauthorized 401- Key missing, revoked or unknown.
forbidden 403- Wrong key kind, or origin not allowed.
not_found 404- Unknown resource or another account’s.
payment_required / insufficient_credit 402- Credit too low for a net order.
invalid_request, unknown_plan, invalid_trip, plan_too_short 422- Parameter refused; explicit message.
conflict, not_refundable, not_topupable, not_remindable 409- The order’s state no longer allows it.
rate_limited 429- 600 requests a minute per key.
payments_closed 503- Payments are not open (live mode).