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

# API reference

> Read-only API keys, the /api/v1 endpoints and signed outbound webhooks — available to a club once the Webhooks & API module is enabled.

<Note>
  **Must know**

  * Webhooks and API keys are behind the `webhooks` module. It ships off; a superadmin enables it per club. Until then **Settings → Webhooks & API** says "Webhooks & API are not enabled for this club".
  * The API is read-only. Today it has one endpoint, `GET /api/v1/programs`, which returns what the club's public site already shows.
  * A key or a signing secret is shown **once**, when it is created or rotated. Copy it then.
</Note>

## Where it lives

**Settings → Webhooks & API** — "Push club events to Zapier, n8n or your own server, and read club data with an API key." Two tabs: **Webhooks** and **API keys**.

## API keys

<Steps>
  <Step title="Create a key">
    On the **API keys** tab, create a key and pick its scopes. The full key is shown once; the table afterwards shows only its prefix, scopes, **Last used**, and whether it is active or revoked.
  </Step>

  <Step title="Call the API">
    Send the key as a bearer token:

    ```bash theme={null}
    curl https://<club>.uplifter-curling.com/api/v1/programs \
      -H "Authorization: Bearer uk_live_<prefix>_<secret>"
    ```
  </Step>

  <Step title="Revoke when done">
    Revoking a key is immediate and permanent. A missing, unknown or revoked key — or a club whose module is off — answers `401`; a key without the needed scope answers `403`.
  </Step>
</Steps>

### Scopes

| Scope | Endpoints today |
| - | - |
| `read:programs` | `GET /api/v1/programs` |
| `read:members` | none yet |
| `read:invoices` | none yet |
| `read:games` | none yet |

The last three scopes can be granted to a key so it is ready when their endpoints ship, but no `/api/v1` route reads them today.

### `GET /api/v1/programs`

Returns the club's **active, non-private** programs (leagues, bonspiels and other programs), ordered by start date then name — never more than an anonymous visitor to the storefront can see.

```json theme={null}
{
  "data": [
    {
      "id": "…",
      "name": "Tuesday Night Mixed",
      "description": "…",
      "type": "LEAGUE",
      "status": "ACTIVE",
      "startDate": "2026-10-06T00:00:00.000Z",
      "endDate": "2027-03-30T00:00:00.000Z",
      "price": 320,
      "capacity": 32,
      "createdAt": "…",
      "updatedAt": "…"
    }
  ]
}
```

## Webhooks

An endpoint is an `https://` URL plus the list of events it wants. "Every subscribed event is POSTed as JSON, signed with the endpoint's secret (X-Uplifter-Signature). Failed deliveries retry after 1 min, 5 min, 30 min, 2 h and 12 h; five dead deliveries in a row switch the endpoint off." Re-enabling the endpoint in Settings resets the count.

### Events

| Event | Fires when | Payload highlights |
| - | - | - |
| `registration.created` | A registration becomes active — storefront checkout, a payment webhook, or proxy registration | enrollment, program, member name and email, invoice |
| `payment.completed` | A card payment is authorised, a checkout is finalised with club credit or a gift card, or staff record an offline payment | payment, invoice reference, amount, method, source |
| `game.updated` | A result is entered or a game is moved / its teams changed | game, program, division, round, draw, sides, reason (`result` or `placement`) |
| `member.updated` | A member is created or edited | member name, email, status, `change` |
| `practice_ice.booked` | A curler (or staff for a curler) reserves ice | reservation, booking, date and times, member |
| `ping` | You press **Send test** | a message; not subscribable |

Every delivery is an envelope: `{ id, event, createdAt, organizationId, data }`. The `id` (`evt_…`) is the same on every endpoint the event fans out to, so receivers can de-duplicate. Payloads carry no personal data beyond the registrant's name and email.

### Verifying the signature

Header: `X-Uplifter-Signature: t=<unix seconds>,v1=<hex>` where `v1` is HMAC-SHA256 over `"<t>.<raw body>"` with the endpoint's secret. Reject deliveries whose `t` is more than 300 seconds from now. The scheme is the same as Stripe's, so a Zapier or n8n "verify a Stripe signature" recipe works after renaming the header. Other headers: `X-Uplifter-Event`, `X-Uplifter-Delivery`, `User-Agent: Uplifter-Webhooks/1.0`.

### Managing endpoints

The **Endpoints** table shows URL, events, an **Enabled** switch, **Last delivery** with its HTTP code and **Dead in a row**. Per endpoint: edit events, **Rotate secret** ("The current secret stops verifying immediately — update your receiver first."), delete, **Send test**, and a **Recent deliveries** panel with status, response code, attempt, next attempt and **Retry**.

**Related:** [Feature overview](/product/feature-overview) · [Which pages exist only in the new look?](/ccm/classic-view/what-is-new-ui-only)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.