<!-- Carebit docs: Getting started -->

# Getting started

This guide walks you from zero to a working request against the Carebit
Developer Platform, and shows how to receive webhook events.

## 1. Create a developer project

First, make sure you have already been added as a staff member to the Carebit
organisation that you want to build an integration for. If you don't already
have a staff member account, please speak to the administrator of your Carebit
organisation as they can add to you as a staff member with a developer role
in **Settings > Staff members** within Carebit.

Sign in to Carebit and go to **Settings > Developer platform > Projects**.
Click to create a new project and give it a descriptive name. You can now pick the API scopes your project
will need (for example `bookings.read`, `bookings.create`) and the webhook events you want to receive. Save the
project.

## 2. Create an API credential

Inside the project, open the **API credentials** tab and click **Create
credential**. Copy the `client_id` and `client_secret` returned by the
form. The `client_secret` is shown once. If you lose it, rotate the
credential rather than creating a duplicate project. Client secrets use a
`carebit_cs_live_...` prefix so leaked values can be classified by secret
scanners. Customer credentials work against the API at
`https://api.carebit.co`.

## 3. Set up webhooks

If your integration needs to react when something happens in Carebit,
register an HTTPS endpoint on the project. Webhooks do not use the
access token from the next step; Carebit POSTs signed JSON to your
URL when a subscribed event occurs.

Open **Settings > Developer platform > Projects > (your project) >
Webhook endpoints**, click **Add endpoint**, and paste the HTTPS URL
that will receive deliveries. Copy the signing secret shown when the
endpoint is created. The secret is shown once and uses a
`carebit_whsec_live_...` prefix. If you lose it, rotate the secret
from the dashboard rather than creating a duplicate endpoint.

Subscribe the endpoint to the event types you need. Webhook
subscriptions are independent from API scopes: selecting an event type
authorizes that endpoint to receive the payload. Verify the
`Carebit-Signature` header against the exact raw request body before
you trust the payload, then return a `2XX` within 20 seconds.

Use **Send test event** in the dashboard to deliver a test
payload with `livemode: false` while you build your receiving endpoint.

See [Webhook setup](/guides/webhook-setup) for the delivery envelope
and headers, [Webhook signatures](/guides/webhook-signatures) for
verification, and [Webhook retries](/guides/webhook-retries) for
retry behavior. The event catalog is on the
[webhooks](/webhooks) page.

## 4. Exchange the credential for an access token

The token endpoint is form-encoded per the OAuth2 spec. Do not send JSON
and do not send an `Authorization: Bearer` header.

<!-- code-tabs -->

### cURL

```bash
curl -X POST "https://api.carebit.co/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id=$CAREBIT_CLIENT_ID" \
  --data-urlencode "client_secret=$CAREBIT_CLIENT_SECRET" \
  --data-urlencode "scope=organization.read bookings.read"
```

### JavaScript

```javascript
const body = new URLSearchParams({
  grant_type: "client_credentials",
  client_id: process.env.CAREBIT_CLIENT_ID,
  client_secret: process.env.CAREBIT_CLIENT_SECRET,
  scope: "organization.read bookings.read",
});

const response = await fetch("https://api.carebit.co/oauth/token", {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body,
});
const { access_token } = await response.json();
```

### Python

```python
import os
import requests

response = requests.post(
    "https://api.carebit.co/oauth/token",
    data={
        "grant_type": "client_credentials",
        "client_id": os.environ["CAREBIT_CLIENT_ID"],
        "client_secret": os.environ["CAREBIT_CLIENT_SECRET"],
        "scope": "organization.read bookings.read",
    },
)
access_token = response.json()["access_token"]
```

### Ruby

```ruby
require "httparty"

response = HTTParty.post(
  "https://api.carebit.co/oauth/token",
  body: {
    grant_type: "client_credentials",
    client_id: ENV.fetch("CAREBIT_CLIENT_ID"),
    client_secret: ENV.fetch("CAREBIT_CLIENT_SECRET"),
    scope: "organization.read bookings.read"
  }
)
access_token = response.parsed_response.fetch("access_token")
```

### PHP

```php
$client = new GuzzleHttp\Client();

$response = $client->post("https://api.carebit.co/oauth/token", [
    "form_params" => [
        "grant_type" => "client_credentials",
        "client_id" => getenv("CAREBIT_CLIENT_ID"),
        "client_secret" => getenv("CAREBIT_CLIENT_SECRET"),
        "scope" => "organization.read bookings.read",
    ],
]);
$accessToken = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR)["access_token"];
```

<!-- /code-tabs -->

The `scope` value must be a subset of the scopes on the developer
project. If you omit `scope`, the token receives every scope on the
project. Requesting a scope the project does not have returns `400`
with `error.code` `invalid_scope`.

The response contains a short-lived `access_token` and a rotating
`refresh_token`. Access tokens live for about one hour. See
[Authentication](/guides/authentication) for the full scope rule, token
refresh, and revocation.

## 5. Make your first request

Call `GET /v1/token` to confirm the access token works. Any valid token
can call this endpoint. It does not require `organization.read`.

<!-- code-tabs -->

### cURL

```bash
curl "https://api.carebit.co/v1/token" \
  -H "Authorization: Bearer $CAREBIT_ACCESS_TOKEN"
```

### JavaScript

```javascript
const response = await fetch("https://api.carebit.co/v1/token", {
  headers: {
    Authorization: `Bearer ${process.env.CAREBIT_ACCESS_TOKEN}`,
  },
});
const token = await response.json();
```

### Python

```python
import os
import requests

response = requests.get(
    "https://api.carebit.co/v1/token",
    headers={
        "Authorization": f"Bearer {os.environ['CAREBIT_ACCESS_TOKEN']}",
    },
)
token = response.json()
```

### Ruby

```ruby
require "httparty"

response = HTTParty.get(
  "https://api.carebit.co/v1/token",
  headers: {
    "Authorization" => "Bearer #{ENV.fetch("CAREBIT_ACCESS_TOKEN")}"
  }
)
token = response.parsed_response
```

### PHP

```php
$client = new GuzzleHttp\Client();

$response = $client->get("https://api.carebit.co/v1/token", [
    "headers" => [
        "Authorization" => "Bearer " . getenv("CAREBIT_ACCESS_TOKEN"),
    ],
]);
$token = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);
```

<!-- /code-tabs -->

A `200 OK` with a JSON body means the credential and token are healthy.
From here, browse the [API reference](/api) for every endpoint
you can call.
