# Map your own ids

Your systems already have ids for locations and brands. Write them onto our records once, and every franchisee
you read comes back with your id in `external_id`. You can then look a location up by your id\:

```bash
curl "https://api.rikor.io/v1/franchisees?external_id=loc_0142" \
  -H "Authorization: Bearer $RIKOR_KEY"
```

Ids live in **your namespace**\: another integrator's ids never collide with yours, and nobody else sees them. These
calls need the `franchisees:map` scope.

## One at a time

```bash
# Set
curl -X PUT https://api.rikor.io/v1/franchisees/66a1d0c9e4b0a1b2c3d4c0f3/external-id \
  -H "Authorization: Bearer $RIKOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "external_id": "loc_0142" }'

# Clear
curl -X DELETE https://api.rikor.io/v1/franchisees/66a1d0c9e4b0a1b2c3d4c0f3/external-id \
  -H "Authorization: Bearer $RIKOR_KEY"
```

An id already used for another location in your namespace is a `409 external_id_taken`.

Partner keys can do the same for brands with `PUT` / `DELETE /v1/franchisors/{id}/external-id`.

## In bulk

`POST /v1/external-ids` takes up to 200 items. Each names exactly one of `franchisee_id` or `franchisor_id`; a
`null` `external_id` clears it.

```bash
curl -X POST https://api.rikor.io/v1/external-ids \
  -H "Authorization: Bearer $RIKOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "franchisee_id": "66a1d0c9e4b0a1b2c3d4c0f3", "external_id": "loc_0142" },
      { "franchisee_id": "66a1d0c9e4b0a1b2c3d4c0f4", "external_id": null }
    ]
  }'
```

The call always answers `200`, with one result per item, so a nightly job retries only the rows that failed\:

```json
{
  "object": "external_id_batch",
  "results": [
    { "franchisee_id": "66a1d0c9e4b0a1b2c3d4c0f3", "external_id": "loc_0142", "result": "set" },
    { "franchisee_id": "66a1d0c9e4b0a1b2c3d4c0f4", "external_id": null, "result": "cleared" }
  ],
  "set": 1,
  "cleared": 1,
  "unchanged": 0,
  "errors": 0,
  "as_of": "2026-10-29T17:02:11.000Z"
}
```

| Row `error.code` | Meaning |
| --- | --- |
| `not_found` | The id is not in your scope |
| `external_id_taken` | Your id already names another record |
| `duplicate_in_batch` | The same external id appears earlier in this batch |
| `partner_only` | Only partner keys can map brand ids |

Brand ids and location ids are separate namespaces\: the same string may name a brand and a location.
