Adresse de base
https://terudo.com/api/partner/v1
Authentification
Envoyez votre clé dans l’en-tête Authorization. Les clés secrètes (sk_…) restent sur votre serveur et voient vos prix nets. Les clés publiables (pk_…) vont dans vos pages pour les Elements et ne voient que les prix publics. Les clés de test (…_test_…) créent des commandes bac à sable : pas de paiement, pas d’eSIM réelle, rien de facturé ; la page de paiement propose un bouton « simuler le paiement ».
curl https://terudo.com/api/partner/v1/me \
-H "Authorization: Bearer sk_test_…"
Deux modèles
Commission : Terudo vend au voyageur, qui paie sur notre page et accepte nos conditions ; vous touchez une commission. Prix net : vous achetez sur votre crédit prépayé et facturez votre client vous-même. Vous choisissez à chaque commande.
Identifiants de forfait
Forfaits fixes : DESTINATION-GO, comme MA-10. Forfaits à la journée : DESTINATION-DAYgo-nD, comme MA-DAY2-8D (2 Go par jour pendant 8 jours). Le devis pour un voyage renvoie le bon identifiant pour les dates données.
Les listes renvoient { object: "list", data: [...] } ; /orders ajoute has_more et accepte starting_after. Les montants sont des entiers en centimes d’euro, TTC pour les prix client, HT pour les prix nets et les commissions. Les dates sont en ISO 8601, UTC.
Les clés et les webhooks se gèrent dans votre espace partenaire, onglet Développeurs, une fois l’API ouverte sur votre compte.
Catalogue
Deux familles de forfaits. Les forfaits fixes de la grille (« MA-10 » : Maroc, 10 Go, 30 jours). Les forfaits à la journée, construits à la demande pour un nombre de jours (« MA-DAY2-8D » : Maroc, 2 Go par jour pendant 8 jours, puis débit réduit). Un identifiant de forfait se passe tel quel à la commande.
GET /destinations Destinations clé secrète
Les destinations du catalogue, avec les identifiants de leurs forfaits fixes et la disponibilité des forfaits à la journée.
Réponse{ "object": "list", "data": [ { "code": "MA", "name": "Maroc", "name_en": "Morocco", "fixed_plans": ["MA-3", "MA-10"], "daily_plans": true }, … ] }
GET /plans Forfaits clé secrète
Les forfaits à votre tarif : prix public conseillé, prix client par défaut, prix net et commission. Avec destination et days, ajoute les forfaits à la journée de cette durée.
destination string- Code ISO (MA) ou région (EU-35). Sans : toute la grille.
days integer 1–30- Durée des forfaits à la journée à ajouter.
Réponse{ "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} Un forfait clé secrète
Un forfait par identifiant, fixe ou à la journée.
POST /quotes Devis pour un voyage clé secrète
Donnez la destination et les dates : la réponse liste les forfaits qui couvrent le séjour et en recommande un, le moins cher qui couvre tout, avec un jour de marge pour un vol en retard. Rien n’est créé.
destination string · requis- Code de la destination.
start_date date · requis- Arrivée, AAAA-MM-JJ.
end_date date · requis- Départ, AAAA-MM-JJ. 60 jours au plus.
profile light | normal | heavy- Usage estimé : 0,5, 1 ou 2 Go par jour. Défaut normal.
buffer_days integer 0–3- Jours ajoutés à la durée couverte. Défaut 1.
Requête{ "destination": "MA", "start_date": "2026-12-03", "end_date": "2026-12-09", "profile": "normal" }
Réponse{ "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} Le forfait du voyageur suffit-il ? toute clé
Quels forfaits mobiles français principaux incluent déjà la destination, d’après nos relevés vérifiés. Avec brand et plan, vérifie un forfait précis. Pour dire la vérité au client avant de vendre.
brand string- Marque du forfait du voyageur (Free, Sosh, …).
plan string- Nom du forfait.
Réponse{ "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 Le téléphone prend-il une eSIM ? toute clé
D’après le modèle tel que le voyageur le donne : yes, depends (certaines versions seulement, la note dit lesquelles), no ou unknown (modèle absent de notre liste, la note décrit la gamme de la marque). Les deux vérifications à faire sur le téléphone accompagnent toujours la réponse : *#06# pour l’EID, téléphone désimlocké.
device string · requis- Modèle : iPhone 13 mini, Galaxy S23, Pixel 7a…
Réponse{ "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é…"] }
Commandes
Deux modèles, à choisir à chaque commande. Commission : Terudo vend au client, qui paie sur notre page (checkout_url) et accepte nos conditions ; vous touchez la commission. Prix net : vous achetez au prix net, pris sur votre crédit prépayé, l’eSIM est livrée aussitôt et vous facturez votre client vous-même. Une commande avec reference est idempotente : la même référence renvoie la même commande.
POST /orders Créer une commande clé secrète
Crée la commande. En commission, renvoie checkout_url à montrer au client (ou notify_client pour que nous lui envoyions le lien). Au prix net, débite le crédit et lance la livraison, tout de suite ou à deliver_at.
plan string · requis- Identifiant de forfait, fixe ou à la journée.
kind commission | net- Défaut commission.
client.email string · requis- Le voyageur. Il reçoit l’eSIM à cette adresse.
client.locale fr | en- Langue des e-mails et de la page de paiement.
reference string ≤ 120- Votre identifiant (dossier, réservation). Unique par compte, clé d’idempotence : la même référence renvoie la même commande (200). Un en-tête Idempotency-Key tient lieu de référence si le corps n’en a pas.
trip.start_date, trip.end_date date- Dates du voyage. Refusé si le forfait est trop court. Pilote les rappels.
discount_percent integer 0–15- Commission seulement. Remise client prise sur votre commission. Défaut 5.
return_url https URL- Où la page de paiement renvoie le client une fois payé.
notify_client boolean- Commission : nous envoyons le lien de paiement par e-mail. Défaut false.
deliver_at datetime ISO 8601- Livraison différée, 90 jours au plus. Ou days_before_trip (entier) avec trip. Un forfait à la journée doit être installé dans les 30 jours : vendu plus de 25 jours avant le voyage, il est livré 7 jours avant le départ, sauf indication contraire.
auto_topup_max integer 0–10- Prix net seulement : forfait dynamique. Quand les données baissent, le même forfait est ajouté depuis votre crédit, au plus ce nombre de fois.
metadata object ≤ 20 clés- Vos données, renvoyées telles quelles.
Requête{ "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" } }
Réponse{
"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 Lister clé secrète
Vos commandes, les plus récentes d’abord, 50 par page (starting_after = id de la dernière). Filtres : reference, status, email.
GET /orders/{id} Une commande clé secrète
Par identifiant Terudo ou par votre reference. Statuts : pending, paid, ordered, delivered, failed, refunded, cancelled, expired. L’objet esim apparaît une fois livrée.
POST /orders/{id}/cancel Annuler clé secrète
Un lien non payé est annulé. Une commande payée est remboursée tant que l’eSIM n’a pas été installée : sur votre crédit au prix net, sur la carte du client en commission.
reason string- Motif, gardé dans le journal.
POST /orders/{id}/remind Relancer le client clé secrète
Renvoie le lien de paiement par e-mail (commission, deux relances au plus, 24 h d’écart).
eSIM
L’identifiant d’une eSIM est celui de l’objet esim de sa commande ; c’est aussi le jeton de la page « Mon eSIM » du client (page_url), que vous pouvez afficher dans votre propre espace.
GET /esims/{id} Une eSIM clé secrète
Statut, installation, consommation, code d’activation, liens d’installation iOS et Android, QR code.
Réponse{
"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 Consommation clé secrète
Données consommées et totales, rafraîchies chez le fournisseur au plus toutes les 10 minutes.
GET /esims/{id}/topups Recharges possibles clé secrète
Le même forfait à nouveau et, pour un forfait à la journée, des jours en plus (1, 3, 7), sur la même eSIM quand le fournisseur le permet.
POST /esims/{id}/topups Recharger clé secrète
Au prix net : la recharge est prise sur le crédit et ajoutée à l’eSIM. En commission : un lien de paiement est ouvert pour le client et renvoyé comme nouvelle commande.
plan string- Un forfait de la même destination. Défaut : celui de l’eSIM.
POST /esims/{id}/resend Renvoyer les instructions clé secrète
Renvoie l’e-mail d’installation (QR code, lien d’installation) à l’adresse du voyageur sur la commande : e-mail perdu, nouveau téléphone. eSIM livrée seulement, trois fois par jour au plus.
POST /esims/{id}/suspend Suspendre clé secrète
Coupe la data d’une eSIM achetée au prix net (voyageur parti, appareil perdu). Rien n’est remboursé, le forfait continue de courir.
POST /esims/{id}/resume Réactiver clé secrète
Rétablit la data.
Webhooks
Nous appelons votre adresse https à chaque étape. Chaque appel porte Terudo-Signature : t=<horodatage>,v1=<HMAC-SHA256 hex de "t.corps" avec le secret de l’adresse>. Vérifiez la signature et rejetez un horodatage de plus de 5 minutes. Les échecs sont réessayés après 1, 5, 30, 120 et 720 minutes ; 25 échecs de suite coupent l’adresse, à réactiver depuis le portail ou l’API. Le corps : { id, type, created_at, mode, data: { order } }.
GET /webhooks Lister clé secrète
Vos adresses dans le mode de la clé, et la liste des événements.
POST /webhooks Créer clé secrète
url https publique (port 443) et events (vide : tous). Le secret est renvoyé.
Requête{ "url": "https://partner.example/hooks/terudo", "events": ["order.paid", "order.delivered", "esim.installed", "esim.low_data"] }
Réponse{ "id": 3, "object": "webhook_endpoint", "url": "https://partner.example/hooks/terudo", "mode": "live", "events": [ … ], "secret": "whsec_…" }
PATCH /webhooks/{id} Modifier clé secrète
url, events, enabled.
DELETE /webhooks/{id} Supprimer clé secrète
POST /webhooks/{id}/test Envoyer un test clé secrète
Un événement test signé, tout de suite.
GET /webhooks/{id}/deliveries Envois clé secrète
Les 100 derniers envois, avec leur état et la réponse de votre serveur.
POST /webhooks/{id}/deliveries/{delivery_id}/resend Renvoyer clé secrète
Elements : la clé publiable
Ces routes servent les Elements dans vos pages, avec une clé pk_… et CORS ouvert aux sites de la clé. Jamais de prix net. Un element_session créé par votre serveur avec la clé secrète débloque la remise client, le tarif member, un voyage et une référence prérenseignés.
POST /element_sessions Session pour une page clé secrète
Renvoie client_token, valable 2 heures, à passer aux Elements (option session).
discount_percent integer 0–15- Remise client sur cette page.
client_email, reference, return_url, locale, metadata - Comme pour une commande.
trip object- destination, start_date, end_date, profile.
GET /public/destinations Destinations clé publiable
GET /public/plans Forfaits au prix public clé publiable
?destination, ?days, ?session.
POST /public/quotes Devis clé publiable
Comme /quotes, au prix public.
POST /public/checkout Paiement hébergé clé publiable
Crée une commande en commission et renvoie checkout_url. 30 par heure et par adresse IP.
plan string · requisemail string · requis- Sauf si la session le porte.
return_url, locale, trip, session - return_url n’est gardé que si son origine figure dans les sites déclarés sur la clé publiable, ou s’il vient de la session signée. Une clé sans liste de sites ne prend aucune adresse de retour depuis la page.
GET /public/esims/{id} Page eSIM clé publiable
Les données de la page « Mon eSIM », sans code d’activation.
Serveur MCP pour les assistants IA
Votre assistant IA (Claude, ChatGPT, tout client MCP) peut chiffrer, vendre et suivre des eSIM pour vous. Le serveur MCP prend les mêmes clés que l’API, fonctionne en bac à sable avec une clé de test, et chaque outil appelle une route de cette référence, avec les mêmes prix et les mêmes erreurs. Transport HTTP « Streamable ».
claude mcp add --transport http terudo https://terudo.com/api/partner/v1/mcp/ --header "Authorization: Bearer sk_test_…"
Autres clients : serveur MCP en HTTP à cette adresse, avec l’en-tête Authorization: Bearer suivi de votre clé. https://terudo.com/api/partner/v1/mcp/
Outils avec une clé secrète
- Compte et catalogue
account, destinations, plans_list, plan_show, quote_trip, coverage_check, compatibility_check- Commandes
orders_list, order_show, order_create, order_cancel, order_remind- eSIM
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- Relevés
statements_list, statement_show
Avec une clé publiable (pk_…), l’assistant vend pour vous sans jamais voir un prix net : prix publics, vérifications avant la vente et lien de paiement sur votre page de paiement. Outils : destinations, plans_list, quote_trip, coverage_check, compatibility_check, checkout, esim_page.
Pour essayer sans compte, prenez notre clé publique de démonstration : vrai catalogue, devis et vérifications, pas de lien de paiement.
claude mcp add --transport http terudo https://terudo.com/api/partner/v1/mcp/ --header "Authorization: Bearer pk_test_terudo_demo_public"
Événements des webhooks
order.paid- Le client a payé (commission), ou le crédit a été débité (prix net).
order.delivered- L’eSIM est envoyée au client ; l’objet esim est renseigné.
order.failed- Le fournisseur n’a pas livré ; nous intervenons.
order.refunded- Remboursée, par vous ou par nous.
order.cancelled- Lien de paiement annulé.
esim.installed- Le profil est installé sur un téléphone.
esim.low_data- Un quart des données ou moins.
esim.used_up- Plus de données.
esim.expiring- Fin de validité proche.
esim.expired- Validité terminée.
esim.deleted- Le client a supprimé le profil du téléphone.
esim.suspended- Data coupée.
esim.resumed- Data rétablie.
topup.delivered- Une recharge est ajoutée à l’eSIM.
Erreurs
Toute erreur a la forme { "error": { "code", "message" } }. Les messages sont en français ; les codes sont stables.
unauthorized 401- Clé absente, révoquée ou inconnue.
forbidden 403- Mauvais type de clé, ou origine non autorisée.
not_found 404- Ressource inconnue ou d’un autre compte.
payment_required / insufficient_credit 402- Crédit insuffisant pour une commande au prix net.
invalid_request, unknown_plan, invalid_trip, plan_too_short 422- Paramètre refusé ; message explicite.
conflict, not_refundable, not_topupable, not_remindable 409- L’état de la commande ne le permet plus.
rate_limited 429- 600 requêtes par minute et par clé.
payments_closed 503- Les paiements ne sont pas ouverts (mode production).