OmniRoam — Roaming Agreements & Email Automation
OmniRoam's agreements side turns the paperwork of setting up a roaming partner — the emails, the AA.12/AA.13 forms, the IOT rates, the SIM swaps, and the provisioning work — into a single tracked record per partner, and automates the parts that used to be copy-and-paste. Its headline trick: forward a partner email to OmniRoam and it reads the thread, plucks out the facts, and updates the agreement for you — then generates and e-signs the contracts, files them, and raises the work orders to get the partner launched.
Two different "OmniRoam"s. This document is about the agreements / email / document side of OmniRoam (the commercial and provisioning lifecycle with a roaming partner). It is not the same as the roaming test books (IR.38 / IR.48 / VoLTE conformance testing) — those are covered separately in OmniRoam — Roaming Test Automation. One product, two jobs: get the agreement signed (here) and prove the roaming works (there).
Table of Contents
- The Big Picture
- 1. Inbound Email Ingestion — "plucking the data out"
- 2. Agreements & Partners
- 3. Automatic Document Generation & Signing
- 4. Filing & Storage
- 5. Work Orders & Assignee Notifications
- The Full Lifecycle, End to End
- What You Set Up Once
The Big Picture
Everything in OmniRoam hangs off one record: the Agreement — one per roaming partner. An agreement carries the partner's name, country, TADIG(s)/PLMN, its lifecycle status, its contacts, the agreed commercial rates, the SIMs exchanged, the generated and received documents, an activity timeline, and the work orders that get the partner live.
You can build all of that by hand in the UI. But the point of OmniRoam is that most of it arrives by email, and OmniRoam files it for you.
The tenant you're working in is an Operator (your own network — the "home" side). Everything is scoped to it: your letterhead and signatory fill the generated documents, your inbound address drives the email automation, and your teams are the work-order assignees.
1. Inbound Email Ingestion — "plucking the data out"
What you do
Negotiating with a partner is an email conversation. To bring it into OmniRoam you
do one thing: forward the email — or CC the OmniRoam inbound address on the
thread. That's it. Your dedicated inbound address (for example
roaming@yourdomain) is configured once per operator (Settings → paperwork
details, Inbound email).
- Forward a whole thread once and OmniRoam builds the agreement from the history buried in the quoted messages.
- CC the address on an ongoing negotiation and every new email keeps the record current — status advances, contacts and TADIGs fill in, rates land, and attached paperwork gets filed, email by email.
You never fill in a form to do this. The email is the input.
What OmniRoam does
Step by step, once a mail reaches OmniRoam:
- It figures out which operator (tenant) the mail is for by matching a To/Cc
address to an operator's configured inbound address. If nothing matches, the
email is logged as
no-operatorand nothing is changed — a safe no-op. - It reads the attachments, not just the body. The agreed rates or the signed terms are often inside an attached AA.13, an IOT rate sheet, or a spreadsheet — so OmniRoam extracts the text from PDF, Word, Excel and CSV attachments and feeds that to the extractor too. Signature-block logos (PNG/JPG) are ignored.
- It extracts the facts using the ChatGPT API. The extractor is specifically told the outer sender is usually just forwarding the thread (often your own roaming manager) and to read the whole quoted history — attributing rates, contacts, addresses and SIMs to whoever actually stated them, never to the forwarder. It returns a structured record: partner name, country, address, TADIG(s)/PLMN, best-fit lifecycle status, agreed rates (only if both sides explicitly agreed), partner contacts, exchanged/requested SIMs, whether a signed agreement is attached, and a one-line summary.
- It finds the right agreement — or creates one. Matching is deliberately forgiving so a thread never spawns a duplicate: exact partner name, then a "normalised name" match (so AT&T Mobility joins AT&T), then a shared PLMN (MCC+MNC) match — a very high-precision signal since a PLMN uniquely identifies a network. No match → a brand-new agreement.
- It merges in only what's new. For both new and existing agreements, OmniRoam
applies whatever this email newly reveals and never clobbers existing
values:
- Status only ever moves forward along the lifecycle (never backwards).
- Country / address set if blank or changed.
- TADIGs added — but only codes that exist in the IR.21 catalog (so the AI can't invent one), and never your own home network's codes.
- Contacts added, or existing ones enriched (blank fields filled in).
- SIMs recorded (test SIMs the partner shared) and SIM requests (batches someone asked to be shipped to an address).
- Agreed rates become a rate tier — only when both sides explicitly agreed, and never a duplicate of an existing tier.
- A signed AA.12/AA.13 (attached, or stated in the mail) advances the status to IRA Signed.
- It writes two records. A friendly activity-log entry on the agreement timeline ("Email from Jane at Partner (forwarded): agreed data rate — status → rates_agreed, added contact Jane, recorded agreed rates"), and a raw inbound audit row (see below).
Processing is idempotent — the same email (by Message-ID) is only ever processed once, so CC'ing multiple people or re-forwarding a thread never double-counts.
Three ways the email gets in
You only need one. All three end up calling the same processing logic:
| Path | How it works | When to use it |
|---|---|---|
| Cloudflare Email Worker | Cloudflare Email Routing forwards the raw message to a small Worker that streams the .eml straight to the OmniRoam webhook. | Domains already using Cloudflare; no mailbox to poll. |
| IMAP poller | OmniRoam logs into a real mailbox every ~60 s, processes unread messages, and flags them read. | Any standard mailbox (implicit TLS, STARTTLS, or plain). |
| Provider inbound-parse | A mail provider (Mailjet/SendGrid) POSTs the parsed message + attachments to the webhook. | If you already run inbound-parse. |
The webhook (/api/roaming/inbound-email) is guarded by a shared secret, so
only your configured mail path can post to it.
The Inbound Email Log — your audit trail
Every processed email — success or failure — writes a row to the Inbound
Email Log (in the UI under the operator's Emails view). Each row shows the
sender, recipients, subject, attachments, whether the AI extraction succeeded,
exactly what it extracted, and what the email changed (or why it did nothing —
no-operator, no-partner). This is your window into the automation: if a rate
didn't get picked up, the log tells you what the extractor actually saw.

The Inbound Email Log — one row per processed email, with the extraction outcome and the changes it made. This is the audit trail for the whole email→agreement automation.
2. Agreements & Partners
The Agreements list is your book of roaming partners for the current operator. Each row is one partner, with its lifecycle status, TADIG/country, priority, and who the next action is waiting on ("Us" or "Them").

The Agreements list. Statuses run left-to-right along the lifecycle; the filter bar narrows by status. Agreements are created here by hand — or automatically from an inbound email.
The lifecycle (status)
An agreement moves forward through these stages. The email automation only ever advances the status, so the record reflects the furthest point the conversation has reached:
Enquired → IOT Negotiation → IOT Pending Signature → IRA Negotiating → Awaiting IRA Signatures → IRA Signed → Rates Agreed → SIM Exchange → Testing → Launched (plus Default Launch, Suspended, Terminated).
Opening a partner
Click a partner to open its detail page — a set of tabs/sections covering everything about the relationship:
- Overview & timeline — status, priority, notes, and the activity log (every email, generated document, signature, and manual note in date order).
- TADIGs — the partner's network codes (with MCC/MNC, connection type and direction). A "find candidates" action can pull the partner operator's other TADIGs from the IR.21 catalog for you to review and add.
- Contacts — roaming/commercial/technical people at the partner.
- Rates — the agreed commercial rate tiers (data/SMS/voice, currency, unit).
- SIMs & SIM requests — test SIMs exchanged, and batches requested for shipping.
- Documents — generated and received paperwork (see below).
- Routing — DRA routes, SS7 global titles, DNS and IP ranges for provisioning (much of it pre-populated from the partner's IR.21).
Everything on the detail page is editable — the automation gives you a head start, and you correct or add by hand as needed.
The IR.21 catalog
TADIG lookups draw on a global IR.21 world-operator catalog keyed by TADIG (organisation, network, MCC/MNC, DNS, IP ranges, SS7 nodes, contacts). This is how OmniRoam validates a TADIG the AI extracted, discovers a partner's sibling TADIGs, and pre-populates routing data.
3. Automatic Document Generation & Signing
Generating a document
On an agreement's Documents section you pick a document kind and click Generate. OmniRoam renders the real Word form, filled with both sides' details, ready to sign:
| Kind | What it is | Format |
|---|---|---|
| AA.12 | GSMA AA.12 IREG roaming agreement (the real form, both sides pre-filled) | .docx / PDF |
| AA.13 | GSMA AA.13 common annexes, including the billing/settlement annex — see AA.13 settlement options | .docx / PDF |
| CLL | Commercial Launch Letter (generic) | .docx / PDF |
| CLL (Bilateral / Unilateral, after testing) | Launch letter confirming the start date after successful IREG & TADIG testing | .docx / PDF |
| CLL (Bilateral / Unilateral, default) | Launch letter for a launch by default, without completing IREG/TADIG testing | .docx / PDF |
| TCC (VoLTE) | VoLTE Test Call Completion | .docx / PDF |
| TADIG completion | TADIG completion form | .docx / PDF |
| TNS Roaming Agreement Form | TNS clearing-house request (delivered as legacy .doc) | .doc |
| TNS 3G-4G Request | TNS clearing-house request | .docx |
How the fields get filled. Each document is a Word template with placeholders (docxtpl / Jinja). OmniRoam fills them from:
- The home side — from your Operator record: your name, legal name, TADIG, PLMN, country, signatory & title, place, and address. Because this comes from the tenant, each hosted operator gets its own letterhead and signatory automatically.
- The partner side — from the Agreement: partner name, its short-form abbreviation used in the contract body, TADIG(s), PLMN(s), country and address. The partner's own signatory/title default blank — that line is left ready for them to sign.
- Derived values — effective date, direction (bilateral/inbound/outbound), hub company, Diameter realms, currency, and the confirmed IOT rate.
Output format — Word by default, PDF for signing
Generation produces an editable Word .docx by default — that is the working
copy you review and hand-edit if needed. You get a PDF only when you actually need
a fixed, final rendering:
- Tick the PDF output checkbox before clicking Generate to render a PDF instead
of the
.docx. - The e-signature flow always uses PDF (the signed artifact must not change).
- Download / preview a filed document as PDF on demand.
A Roaming Pack email attaches the AA.12/AA.13 as editable .docx so the partner
can review and comment — it is not the signing step, so it is not sent as PDF.
AA.13 settlement options (Annex C.3.2)
GSMA AA.13 Annex C.3.2 (billing & settlement) is a menu of choices each partner negotiates — which invoice model, which payment method, the settlement threshold and period, payment terms, and interest. Rather than lock one set of choices into the template, OmniRoam exposes them as a settlement-options panel on the Documents section: expand AA.13 settlement options, set the values for this partner, then click Generate AA.13. The generated annex contains only the options you chose — the alternatives (and the GSMA "delete those which do not apply" scaffolding) are dropped automatically.
Every field has a sensible default, so generating without touching the panel yields the standard terms; change only what differs for a given partner.
| Option | Default | Description |
|---|---|---|
| Invoice type | Single-network invoice (SNI) | Selects the settlement annex: Single-network (SNI) → Annex C.3.2 H, or Multi-network (MNI) → Annex C.3.2 I. The unused annex is removed. |
| Payment method | Net settlement | The settlement mechanism: Net settlement, Direct full payment (no conversion), Direct full payment (with conversion), or Netting without conversion. Only the chosen method's clause is kept. |
| Threshold settlement | Option 1 — Netting | Option 1 (Netting) applies a single agreed low-balance threshold; Option 2 (Direct payment) uses per-party (Party A / Party B) thresholds. |
| Threshold | 50 | Low-balance settlement threshold amount, in the agreement's settlement currency (e.g. SDR). Below this monthly aggregate, settlement may be deferred. |
| Period start / Period end | January / December | The non-settlement period for balances below the threshold — typically the financial year. |
| Payment days | 60 | Days from the invoice date within which the debtor must pay. |
| Interest home % | 8 | Annual interest the creditor may charge on overdue balances when the home operator is the creditor. |
| Interest partner % | 8 | Annual interest when the partner operator is the creditor. |
| Send zero-value invoices | Off | When off, the annex states each party will not send monthly invoices with a zero (0.00) amount. |
| BCE on TAP invoice | Off | When off, the annex states BCE usage will not be included on the TAP Roaming Invoice. |
How it works. The choices are passed to generation as overrides on top of the built-in defaults; the AA.13 template resolves them into the finished annex — selecting the right option blocks, filling the amounts/periods/rates, and phrasing the toggles. The settlement currency itself comes from the agreement's configured currency, not this panel.
Use case. A partner insists on 90-day terms, a 100-SDR threshold and an April–March financial year: open the panel, set Payment days 90, Threshold 100, Period start April, Period end March, and generate. Every other clause stays at the standard terms.
The TNS clearing-house forms are special. The two TNS requests are not docxtpl templates — they are the operator's genuine TNS forms with only the fillable fields changed and the right checkboxes ticked, so TNS receives exactly the layout it expects. They're IOT-gated: OmniRoam won't generate them until the agreement has a confirmed (agreed) rate — trying earlier returns a clear "a confirmed IOT is required" message. The checkbox states (agreement type, direction, services, LTE interfaces, GRX) are auto-derived from the agreement, and all fields are overridable at generation time.
Generation to PDF (and the legacy .doc for TNS) is done by headless LibreOffice
on the server — you just get the finished file.

The Documents section of an agreement. Generate a contract on the left; generated and received documents (with signing status) list below, each downloadable.
Signing — online or offline
OmniRoam supports two signing routes:
Online e-signature (partner signs in the browser, no login). From a generated AA.12/AA.13 you click Send for signature, name the signer and their email, and OmniRoam:
- Creates a signature request with an opaque token and emails the partner a secure link (no account needed).
- When they open it, OmniRoam marks the request viewed and logs it on the timeline. They review the document, optionally correct their signatory name/title/company, and sign — typing their name and/or drawing a signature.
- OmniRoam produces the signed PDF and emails it to both parties (signer + your operator's return mailbox), files it on the agreement, and logs "Signed by … on …".
- The partner can also decline (with a reason), which is recorded too.
Offline signing. Prefer to sign the old way? Download the generated document, sign it externally, and upload the signed copy back onto the agreement. A filename containing signed/executed/countersigned is recognised as a signed copy — and an inbound email that attaches one advances the status to IRA Signed automatically.
The Roaming Pack — one-click first contact
Instead of generating each form separately, Send roaming pack emails a partner contact the AA.12 + AA.13 + IOT offer together in one message, generating the contracts as PDFs on the fly and attaching your most recent IOT offer. Pick a contact (or type a name + email — it's backfilled as a contact), and OmniRoam sends the pack with your saved template wording. This is the "let's do a roaming deal" opening email, sent from inside OmniRoam.
Editable email templates
The three automated emails — signature request, signed copy, and roaming
pack — use editable templates (per-operator override, else a global default),
with placeholders like {{ signer_name }}, {{ partner }}, {{ operator }},
{{ sign_url }} and {{ document_name }}. Tune the wording once in Settings and
every send uses it.
How email actually leaves OmniRoam. All outbound mail goes via the Mailjet HTTPS Send API, not SMTP. Hosting platforms (Railway) block outbound SMTP ports, so OmniRoam POSTs to Mailjet over HTTPS instead. Sends are best-effort and non-blocking: the UI button returns immediately and the mail goes out on a background thread, so a slow mail server never stalls the app.
4. Filing & Storage
Every document — generated (AA.12, AA.13, CLL, TCC, TNS…) or received (a signed copy attached to an email, an uploaded IR.21, an IOT sheet) — is filed directly on the agreement it belongs to. There's no separate document store to manage:
- Documents are stored as blobs in the database, tagged with a kind
(
aa12,aa13,aa12_signed,iot,ir21,cll,other, …), filename, content type, size, and whether OmniRoam generated it. - Signed copies are tagged distinctly (e.g.
aa12_signed) so the signed set is always distinguishable from drafts. - Inbound attachments are de-duplicated — an identical copy (same filename + byte length) that arrives again is not re-filed.
- Every generation, upload, signature, and IOT export writes a timeline entry, so the agreement's activity log is a complete paper trail of what was produced and received, and when.
To retrieve a document, open the agreement's Documents section and download it (generated Word/PDF, or the received original). Signed PDFs produced by the online signing flow are stored on the signature request and also emailed to both parties.
You can also export the agreed rate as a GSMA RAEX IOT 5.0 XML file from the agreement — the same rate selection the TNS forms use, so the exported IOT and the generated forms always agree.
5. Work Orders & Assignee Notifications
Getting a partner live is work — shipping SIMs, changing routing, running IREG/ TADIG tests, audits, chasing issues. In OmniRoam that work is tracked as Work Orders: the single tracked unit of roaming work. A work order can hang off an agreement (a partner) or stand alone.

The Work Orders view. Each order has a type, priority, status, optional partner link, and an assignee — the party notified when it's assigned.
Creating and assigning
A work order has a type (SIM Dispatch, Routing, IREG Testing, TADIG Testing, Audit, Issue), a title, priority, status (Open / In Progress / Blocked / Done / Cancelled), an optional partner (agreement) link, free-text details, a due date, and type-specific structured fields (e.g. a SIM Dispatch carries quantity, postal address, carrier and tracking).
You assign a work order to a party — a named internal team or external contact (e.g. "Roaming NOC", "TADIG admin") managed per operator in Settings. You can set a default assignee per work-order type, so a new SIM Dispatch auto-assigns to whoever handles dispatch unless you override it.
The notification — webhook + email
When a work order is assigned (created with an assignee, or re-assigned to a new party), OmniRoam notifies that assignee through whatever channels the party has configured:
- Webhook — if the party has a webhook URL (e.g. a Slack incoming
webhook), OmniRoam POSTs a message with a human-readable
textblock and the full work-order as structured JSON (type, priority, status, partner, the type-specific payload, a link back to the Work Orders page). - Email — if the party has an email address, OmniRoam sends the same detail as
an email (via Mailjet), subject
[Work Order] <title> assigned to you.
A party with neither channel set is simply a silent assignee (no-op). Both notifications are best-effort and non-blocking — a slow webhook or mail server can never stall the app — and re-assignment only notifies when the assignee actually changes to a new party (so editing other fields doesn't re-ping people).
From the assignee's chair: you get a Slack message (or email) the moment a job lands on your team, with everything you need — what to do, for which partner, the SIM count and shipping address (or the routing change, or the test scope), the priority and due date, and a link straight to the work order.
The Full Lifecycle, End to End
Putting it all together — the journey from "a partner emailed us" to "the partner is live":
At every step the agreement's timeline records what happened, and the inbound email log keeps the raw evidence of what each email contributed.
What You Set Up Once
Most of the automation just needs a little one-time configuration per operator (in Settings):
| Setting | Why | Where it's used |
|---|---|---|
| Paperwork details (legal name, TADIG, PLMN, country, signatory & title, place, address) | Fills the home side of every generated document | Document generation |
| Inbound email address | The address you forward/CC partner mail to | Email ingestion |
| Signed-return mailbox | Where offline-signed and signed-copy emails go | Signing |
| Email templates (signature request, signed copy, roaming pack) | Your wording for the automated emails | Outbound email |
| Work-order parties + per-type default assignees | Who gets notified for each kind of work | Work orders |
With those in place, forwarding a partner email really does become: email in → agreement out → contracts generated and signed → work orders raised and your team notified.
See Also
- OmniRoam — Roaming Test Automation — the other OmniRoam: running the GSMA roaming test books (IR.38 / IR.48 / VoLTE) against a live network. Complementary to this: sign the agreement here, prove it works there.
- Common Operations — the viewing/editing patterns shared across all of OmniWeb.