# Authentication

This page covers **API keys**, which suit integrating a single workspace. If you
are building an app that many workspaces connect to, use
[OAuth 2.0](/oauth) instead — the rest of these docs apply the same way to both.

Send your API key as a bearer token:

```bash
curl https://api.wearenoe.fr/v1/me \
  -H "Authorization: Bearer noe_live_..." \
  -H "X-Noe-App: your-integration-key"
```

`X-Api-Key: noe_live_...` is accepted as an alternative if your HTTP client
makes that easier.

## The `X-Noe-App` header

Send your integration key on every request. The API key alone already
identifies you, so this header is not what authorises the call — it is a safety
check. If a key ends up configured in the wrong system, the mismatch fails
loudly with `app_mismatch` instead of quietly succeeding against the wrong
workspace's data.

## Where keys come from

Keys are issued by the **workspace owner**, not by Noé and not by you. In their
Noé account they open **Mon compte → API**, click **Créer une clé**, choose the
permissions (scopes) and optionally the IP addresses allowed to use it, and send
you the key. If your company is a registered Noé partner app, they authorise your
app there instead and generate the key from it.

The key is shown **once**, at creation. It cannot be retrieved afterwards — we
store only a hash of it. If it is lost, the workspace generates a new one.

## Environments

| Prefix | Base URL |
| --- | --- |
| `noe_live_` | `https://api.wearenoe.fr/v1` |

There is no sandbox environment. Every key reaches the workspace's real data,
and calendar writes are pushed to the connected OTAs (Airbnb, Booking.com…), so
test your writes on one property the workspace agrees to use for testing.

## Verify a key

`GET /v1/me` describes the credential you are calling with — the workspace, your
scopes, any property restriction and your rate limits. It is the fastest way to
confirm a key works and to see what it can reach before you write anything else.

```bash
curl https://api.wearenoe.fr/v1/me -H "Authorization: Bearer $NOE_API_KEY"
```

```json
{
  "object": "credential",
  "environment": "live",
  "workspace": { "id": "…", "slug": "belle-vue" },
  "integration": { "key": "jaffichecomplet", "name": "J'affiche Complet" },
  "scopes": ["properties:read", "reservations:read", "calendar:read"],
  "property_scope": null,
  "rate_limits": { "per_minute": 300, "per_day": 20000 }
}
```

`property_scope: null` means every property in the workspace, including any
added later. A list means exactly those and nothing else.

## When a key stops working

Each failure has its own code, so you can tell them apart and respond correctly:

| Code | Meaning | What to do |
| --- | --- | --- |
| `missing_credentials` | No key on the request | Add the `Authorization` header |
| `invalid_credentials` | Key not recognised | Check the environment and for truncation |
| `key_revoked` | The workspace revoked this key | Ask them to issue a new one |
| `key_expired` | The key passed its expiry | Ask them to issue a new one |
| `grant_revoked` | The workspace withdrew your access | Contact the workspace |
| `integration_suspended` | Noé suspended your integration | Contact Noé support |
| `app_mismatch` | `X-Noe-App` does not match the key | Fix the configured integration key |
| `ip_not_allowed` | Calling from an address outside the allowlist | Ask the workspace to allow your egress IP |

Treat `key_revoked`, `grant_revoked` and `integration_suspended` as permanent:
stop retrying and surface the problem, because no amount of retrying will fix
any of them.

## Keeping a key safe

- Store it as a secret, alongside your other credentials. Never commit it, and
  never put it in front-end code.
- Call from a server. The API is not designed for browser use and is not
  CORS-enabled for arbitrary origins.
- Ask the workspace to add an **IP allowlist** to the key. It costs them one
  field and makes a leaked key useless from anywhere but your servers.
- Use a **separate key per environment**, so rotating one never takes the other
  down.
