> ## Documentation Index
> Fetch the complete documentation index at: https://partner-help.letsdothis.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scoped API keys

> Give a partner a key that can only check registrations for the event occurrences you choose.

An API key normally has access to everything in your organization. When a partner — a sponsor validating a discount at their checkout, a timing provider, a supplier — only needs one answer from you, you can give them a key that can get that answer and nothing else.

A scoped key can **check whether an email is registered** for the event occurrences you choose. It cannot list participants or bookings, read or change event setup, or reach any other part of the API. The partner sees a yes or a no; they never see participant details.

## Creating a scoped key

In the dashboard, go to **Settings** → **Credentials** → **Public API** and choose **Create new key**. Under **What can this key do?** choose **Only check registrations for specific events**, then add every occurrence the partner should be able to check — the event, then the edition. Restrictions are part of the key from the moment it is minted: there is no window in which it is unrestricted.

The key itself looks and behaves like any other API key — same header, same base URLs.

## Changing which occurrences a key can check

Open the key's menu in **Settings** → **Credentials** → **Public API** and choose **Edit restrictions**. Add or remove occurrences and save; the secret does not change, so the partner holding the key does not need to do anything. The new scope applies within a minute. This is how to roll a partner's key over to next year's edition without re-issuing it.

The same screen lets you switch the key to **Everything in your organization**, which removes its restrictions entirely. Revoking a key also takes up to a minute to propagate.

## What the partner can call

With the key, the partner calls the registration check for one of the chosen occurrences:

```bash theme={null}
curl --request POST \
  --url "https://api.letsdothis.com/v0/event-occurrences/12345678901/registration-status" \
  --header "Authorization: Bearer PARTNER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "email": "runner@example.com" }'
```

```json theme={null}
{ "eventOccurrenceId": "12345678901", "registered": true }
```

An email that is not registered answers `false` rather than an error. Matching ignores case and surrounding whitespace. See [Check whether an email is registered](/api-reference/endpoints/eventoccurrences/check-whether-an-email-is-registered) for the full contract.

### What the partner gets everywhere else

Any call outside the key's scope is refused before any data is read, and the message says why. An occurrence you did not choose:

```json theme={null}
{
  "statusCode": 403,
  "error": "Forbidden",
  "message": "This API key is not permitted to access event occurrence 12345678902"
}
```

Any other endpoint — including `GET /v0/participants`, even for a chosen occurrence:

```json theme={null}
{
  "statusCode": 403,
  "error": "Forbidden",
  "message": "This API key is not permitted to call this endpoint"
}
```

A `403` means the key is working but the call is out of scope; a `401` means the key itself is invalid or has been revoked. Participant and booking lists stay with your own unrestricted keys.

## Checking a key's scope

`GET /identity` is always available to a scoped key and returns what it can reach:

```bash theme={null}
curl --request GET \
  --url "https://api.letsdothis.com/identity" \
  --header "Authorization: Bearer PARTNER_API_KEY"
```

```json theme={null}
{
  "organiserId": "81274",
  "eventOccurrenceIds": ["12345678901"],
  "endpoints": ["registrationStatus"]
}
```

This is the stored shape of a scoped key: the occurrences you chose, and the registration check as the one endpoint it may call. The `endpoints` values are stable names rather than URLs, so a key stays valid if an endpoint's path changes.

## Under the hood

Restrictions are stored as two independent lists — event occurrences and endpoints — and each is enforced on its own. A key can carry either or both:

* **Both lists** — the dashboard's **Only check registrations for specific events** option. The key can call the registration check, for the chosen occurrences only.
* **Endpoints only** — the key can call the listed endpoints for any occurrence in your organization. With `registrationStatus` alone, that is a registration check across every event you run.
* **Occurrences only** — the key can call every occurrence-scoped endpoint, but only for the chosen occurrences. Today that is the registration check; as more occurrence-scoped endpoints are opened up, such a key reaches them automatically. Endpoints that are opened to scoped keys without being tied to an occurrence stay off-limits to it.

Keys created through GraphQL, or before the dashboard option existed, may carry one list without the other; the dashboard shows those as **Custom restrictions** and lets you edit each list directly.

Every endpoint that supports scoped keys says so on its own page. Others — including ones that name an occurrence in their URL — are reserved for unrestricted keys and answer `403` to a scoped one.
