# Roamic Affiliates Feed

> JSON feeds with the full Roamic travel eSIM catalog for affiliate partners.
> Base URL: https://feeds.roamic.com with no auth, no pagination, no API keys.
> CORS is open (`access-control-allow-origin: *`). Responses cache for 5 minutes.

## Endpoints

| Method | Path | Returns |
|---|---|---|
| GET | `/dataPlans` | Array of every purchasable plan |
| GET | `/links` | Array with one landing link per destination |
| GET | `/{partner}/dataPlans` | Same catalog (identical for every partner) |
| GET | `/{partner}/links` | Links, pre-wrapped if the partner has a tracking link configured |
| GET | `/health` | Counts and sync warnings, JSON |

`{partner}` is the partner name agreed with the Roamic affiliate manager.
Lowercase letters, numbers, hyphen, underscore. Any name works.

## dataPlans schema

Array of objects:

| Field | Type | Meaning |
|---|---|---|
| `planName` | string | Display name, unique per plan |
| `validity` | integer | Max duration in days without an extra payment |
| `dataCap` | number | High speed data allowance BEFORE throttling, in `dataUnit` |
| `dataUnit` | string | Always `"GB"` today |
| `dataCapPer` | string or null | `"day"` means the allowance renews daily (unlimited plans). `null` means one total allowance |
| `reducedSpeed` | string | Unlimited plans only: speed after the daily allowance is used, e.g. `"1 Mbps"`. Absent when unknown |
| `prices` | object | Final public checkout price keyed by ISO 4217. `EUR` is the base currency and is always present. Also served when available: USD, GBP, CAD, AUD, DKK, SEK, CHF, JPY (real per market store prices, not conversions made by us) |
| `internetBreakouts` | array | Where traffic exits to the public internet, ISO 3166-1 alpha-2, e.g. `["FR","NL"]`. Absent when unknown |
| `coverages` | array | Covered countries as `{ "code": "JP", "networks": [...] }`, ISO 3166-1 alpha-2. `networks` lists local operators with their top technology, e.g. `{ "name": "NTT docomo", "type": "5G" }`. Absent when unknown |

Fixed plan:

```json
{
  "planName": "Japan eSIM 3GB / 14 Days",
  "validity": 14,
  "dataCap": 3,
  "dataUnit": "GB",
  "dataCapPer": null,
  "prices": { "EUR": 2.99, "USD": 3, "GBP": 3, "CAD": 5, "AUD": 5,
              "DKK": 23, "SEK": 34, "CHF": 3, "JPY": 600 },
  "internetBreakouts": [ "HK" ],
  "coverages": [ { "code": "JP", "networks": [
    { "name": "NTT docomo", "type": "5G" },
    { "name": "SoftBank", "type": "5G" } ] } ]
}
```

Unlimited plan (full speed up to `dataCap` per `dataCapPer`, then `reducedSpeed`):

```json
{
  "planName": "Japan eSIM Unlimited Data / 1 Day",
  "validity": 1,
  "dataCap": 3,
  "dataUnit": "GB",
  "dataCapPer": "day",
  "reducedSpeed": "1 Mbps",
  "prices": { "EUR": 2.99, "USD": 3, "GBP": 3 },
  "internetBreakouts": [ "HK" ],
  "coverages": [ { "code": "JP", "networks": [
    { "name": "NTT docomo", "type": "5G" } ] } ]
}
```

Plans named "Unlimited" are speed-tiered: `dataCap` is the real daily high
speed allowance, which is what comparison sites must display.

## links schema

Array of objects:

| Field | Type | Meaning |
|---|---|---|
| `name` | string | Call to action text, for example `"Japan eSIM"` |
| `link` | string | Landing page URL |
| `type` | string | Always `"web"` |
| `targets` | array | ISO 3166-1 alpha-2 codes where the link applies |

```json
{
  "name": "Japan eSIM",
  "link": "https://roamic.com/products/japan-esim",
  "type": "web",
  "targets": [ "JP" ]
}
```

## Tracking rules

- By default `link` is a pure product URL. No utm, no ref, no query string.
- Roamic's affiliate program runs on impact.com. If you are a partner there,
  wrap each link with your own impact deep link, passing the URL encoded
  landing page in the `u` parameter.
- Or ask the Roamic affiliate manager to configure your tracking link server
  side. Then `/{yourname}/links` returns every link already wrapped, like
  `https://TRACKING_DOMAIN/c/PARTNER/AD/CAMPAIGN?u=https%3A%2F%2Froamic.com%2F...`

## Freshness guarantees

- The catalog is rebuilt from the live store once a day. The
  `x-feed-updated` response header carries the refresh timestamp (ISO 8601).
- Sold out plans and unpublished destinations never appear.
- `prices.EUR` is the final checkout amount a customer pays.
- If it is in the feed, a customer can buy it. Prices and plans change
  rarely, so polling the feed daily is enough.

## Quick check

```sh
curl -s https://feeds.roamic.com/health
curl -s https://feeds.roamic.com/dataPlans | head -c 400
```

Human readable docs: https://feeds.roamic.com/
Questions: contact your Roamic affiliate manager.
