# Create an availability or unavailability period

`POST /v1/availability_periods`

Set `is_recurring` to `false` for a one-off period and supply `start_time` and `end_time`. Set `is_recurring` to `true` for a repeating period and choose `simple` or `advanced` as the `recurring_strategy`. A simple weekly Tuesday uses `recurring_strategy: "simple"`, `recurring_day_number_of_week: 2`, `recurring_interval_in_seconds: 604800`, and a Tuesday `recurring_start_date`. A simple fortnightly period uses 1209600 seconds. The second Thursday of every month uses `recurring_strategy: "advanced"`, `recurring_nth_day_in_month: 2`, `recurring_day_number_of_week: 4`, and a matching start date such as `2026-01-08`. Add `recurring_dates_to_skip: ["2026-02-12"]` to omit that specific monthly occurrence. Recurring start and end times use the Organization's local time.

**Required API scopes:** `availability_periods.create`

## Parameters

- `Idempotency-Key` (header, `string`) (required) - Client-generated idempotency key. Required for every POST/PATCH write. Replay of the same key with the same body returns the stored response with an `Idempotency-Replayed: true` header. Same key + different body returns `422 idempotency_key_reused`. A duplicate that arrives while the first request is still in flight returns `409 idempotency_conflict` with `Retry-After: 1`.

## Request body (`application/json`)

- `object`
  - `availability_type` (`string`) - enum: `availability`, `unavailability`; Whether the period makes the Clinician available or unavailable.
  - `clinician_id` (`string | null`) - format: `uuid`; The Clinician affected by the period.
  - `end_time` (`string | null`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.
  - `is_active` (`boolean`) - Whether the period contributes to the diary.
  - `is_recurring` (`boolean`) - Whether the period repeats. When false, supply `start_time` and `end_time`; recurring fields are cleared.
  - `notes` (`string | null`) - Internal notes about the period.
  - `recurring_dates_to_skip` (`array`) - Specific ISO 8601 dates on which a recurring period must not occur. For example, `["2026-02-12"]` skips the occurrence on 12 February 2026. Only dates that are today or in the future are retained.
    - `items` (`string`) - format: `date`
  - `recurring_day_number_of_week` (`integer | null`) - The ISO weekday number used by a recurring period. The values start at 1, not 0: 1 is Monday, 2 is Tuesday, 3 is Wednesday, 4 is Thursday, 5 is Friday, 6 is Saturday, and 7 is Sunday.
  - `recurring_end_date` (`string | null`) - format: `date`; The optional final recurrence date. It must be after `recurring_start_date`.
  - `recurring_end_time` (`string | null`) - The end time for each recurring occurrence in the Organization's local time.
  - `recurring_interval_in_seconds` (`integer | null`) - Required for `simple`. Use 604800 for weekly or 1209600 for every two weeks.
  - `recurring_nth_day_in_month` (`integer | null`) - Required for `advanced`. Use 2 with weekday 4 for the second Thursday of each month.
  - `recurring_start_date` (`string | null`) - format: `date`; The first recurrence date. Supply a date that matches `recurring_day_number_of_week`.
  - `recurring_start_time` (`string | null`) - The start time for each recurring occurrence in the Organization's local time.
  - `recurring_strategy` (`string | null`) - enum: `simple`, `advanced`, `null`; Select `simple` for a fixed interval measured in seconds, such as every week or every two weeks. Select `advanced` for an occurrence such as the second Thursday of every month. Use null for a non-recurring period.
  - `room_id` (`string | null`) - format: `uuid`; The Room affected by the period.
  - `service_variant_ids` (`array`) - The ServiceVariants offered during an availability period.
    - `items` (`string`) - format: `uuid`
  - `start_time` (`string | null`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.

### Example

```json
{
  "availability_type": "unavailability",
  "clinician_id": "00000000-0000-4000-8000-000000000002",
  "end_time": "2026-01-01T10:30:00Z",
  "is_active": true,
  "is_recurring": false,
  "notes": "Team meeting",
  "start_time": "2026-01-01T10:00:00Z"
}
```

## Response `201`

The requested `AvailabilityPeriod`.

- `object`
  - `availability_type` (`string`) - enum: `availability`, `unavailability`; Whether the period makes the Clinician available or unavailable.
  - `clinician_id` (`string | null`) - format: `uuid`; The Clinician affected by the period.
  - `created_at` (`string`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.
  - `end_time` (`string | null`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.
  - `id` (`string`) - format: `uuid`; The resource's unique identifier, formatted as an RFC 4122 version 4 UUID.
  - `is_active` (`boolean`) - Whether the period contributes to the diary.
  - `is_recurring` (`boolean`) - Whether the period repeats. When false, use `start_time` and `end_time`; recurring fields are cleared.
  - `links` (`object`) - URLs to related resources.
    - `clinician` (`string | null`) - format: `uri`; The full URL of a related resource.
  - `notes` (`string | null`) - Internal notes about the period.
  - `object` (`any`) - Discriminator value emitted at `object`.
  - `recurring_dates_to_skip` (`array`) - Specific ISO 8601 dates on which a recurring period must not occur. For example, `["2026-02-12"]` skips the occurrence on 12 February 2026. Only dates that are today or in the future are retained.
    - `items` (`string`) - format: `date`
  - `recurring_day_number_of_week` (`integer | null`) - The ISO weekday number used by a recurring period. The values start at 1, not 0: 1 is Monday, 2 is Tuesday, 3 is Wednesday, 4 is Thursday, 5 is Friday, 6 is Saturday, and 7 is Sunday.
  - `recurring_end_date` (`string | null`) - format: `date`; The optional final date on which the recurrence can apply. It must be after `recurring_start_date`.
  - `recurring_end_time` (`string | null`) - The end time for each recurring occurrence in the Organization's local time.
  - `recurring_interval_in_seconds` (`integer | null`) - Required for the `simple` strategy. Use 604800 for weekly or 1209600 for every two weeks.
  - `recurring_nth_day_in_month` (`integer | null`) - Required for the `advanced` strategy. For example, use 2 with weekday 4 for the second Thursday of each month.
  - `recurring_start_date` (`string | null`) - format: `date`; The first date on which the recurrence can apply. Supply a date that matches `recurring_day_number_of_week`.
  - `recurring_start_time` (`string | null`) - The start time for each recurring occurrence in the Organization's local time.
  - `recurring_strategy` (`string | null`) - enum: `simple`, `advanced`, `null`; Select `simple` for a fixed interval measured in seconds, such as every week or every two weeks. Select `advanced` for an occurrence such as the second Thursday of every month. Use null for a non-recurring period.
  - `room_id` (`string | null`) - format: `uuid`; The Room affected by the period.
  - `service_variant_ids` (`array`) - The ServiceVariants offered during an availability period.
    - `items` (`string`) - format: `uuid`
  - `start_time` (`string | null`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.
  - `updated_at` (`string`) - format: `date-time`; An ISO 8601 timestamp in UTC, with a `Z` suffix. For example, `2026-07-01T09:00:00Z`.

### Example

```json
{
  "id": "5267a739-2a80-4eaa-80c5-4baeb6a766a9",
  "object": "availability_period",
  "availability_type": "availability",
  "clinician_id": "2b3c4d5e-6f70-489a-9bcd-ef0123456789",
  "created_at": "2026-01-01T09:00:00Z",
  "end_time": "2026-01-01T10:00:00Z",
  "is_active": true,
  "is_recurring": true,
  "links": {
    "clinician": "https://api.carebit.co/v1/clinicians/2b3c4d5e-6f70-489a-9bcd-ef0123456789"
  },
  "notes": "Please confirm the appointment by email.",
  "recurring_dates_to_skip": [
    "2026-01-01"
  ],
  "recurring_day_number_of_week": 1,
  "recurring_end_date": "2026-12-31",
  "recurring_end_time": "17:00:00",
  "recurring_interval_in_seconds": 1,
  "recurring_nth_day_in_month": 1,
  "recurring_start_date": "2026-01-01",
  "recurring_start_time": "09:00:00",
  "recurring_strategy": "simple",
  "room_id": "4d5e6f70-8192-4abc-bdef-0123456789ab",
  "service_variant_ids": [
    "6f708192-a3b4-4cde-9f01-23456789abcd"
  ],
  "start_time": "2026-01-01T09:00:00Z",
  "updated_at": "2026-01-01T09:00:00Z"
}
```

## Response `400`

The `Idempotency-Key` header is missing (`idempotency_key_required`) or exceeds 255 characters (`idempotency_key_too_long`).

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `401`

The access token is missing, invalid, expired, or revoked.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `403`

The access token lacks the required scope, or the project is disabled.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `404`

A referenced resource was not found in the Organization.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `409`

A concurrent request holds the idempotency lease (`idempotency_conflict`). Retry after the delay indicated by `Retry-After`.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `422`

The `Idempotency-Key` was previously used with a different request body (`idempotency_key_reused`), or the request body failed validation.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Response `429`

Too many requests. Retry after the delay indicated by `Retry-After`.

- `object`
  - `error` (`object`) - The structured details that describe why the request failed.
    - `code` (`string`) - The machine-readable error code.
    - `errors` (`array | null`) - Additional errors from a failed validation.
      - `items` (`object`)
        - `code` (`string`) - The machine-readable code for this validation error.
        - `message` (`string`) - A message that explains this validation error.
        - `param` (`string | null`) - The name of the parameter that caused this validation error, when known.
    - `message` (`string`) - A message that explains the error and how to resolve it.
    - `param` (`string | null`) - The name of the parameter that caused the error, when known.
    - `type` (`string`) - enum: `authentication_error`, `permission_error`, `invalid_request_error`, `rate_limit_error`, `api_error`; The high-level category of the error.

### Example

```json
{
  "error": {
    "code": "resource_missing",
    "errors": [
      {
        "code": "resource_missing",
        "message": "The requested resource was not found.",
        "param": "patient_id"
      }
    ],
    "message": "The requested resource was not found.",
    "param": "patient_id",
    "type": "authentication_error"
  }
}
```

## Code samples

```bash
curl -X POST "https://api.carebit.co/v1/availability_periods" \
  -H "Authorization: Bearer $CAREBIT_ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "availability_type": "unavailability",
  "clinician_id": "00000000-0000-4000-8000-000000000002",
  "end_time": "2026-01-01T10:30:00Z",
  "is_active": true,
  "is_recurring": false,
  "notes": "Team meeting",
  "start_time": "2026-01-01T10:00:00Z"
}'
```

```javascript
const response = await fetch("https://api.carebit.co/v1/availability_periods", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CAREBIT_ACCESS_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
  "availability_type": "unavailability",
  "clinician_id": "00000000-0000-4000-8000-000000000002",
  "end_time": "2026-01-01T10:30:00Z",
  "is_active": true,
  "is_recurring": false,
  "notes": "Team meeting",
  "start_time": "2026-01-01T10:00:00Z"
}),
});

if (!response.ok) {
  throw new Error(`Carebit API error: ${response.status}`);
}

const data = await response.json();
```

```python
import os
import requests
import uuid

response = requests.post(
    "https://api.carebit.co/v1/availability_periods",
    headers={
        "Authorization": f"Bearer {os.environ['CAREBIT_ACCESS_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "availability_type": "unavailability",
        "clinician_id": "00000000-0000-4000-8000-000000000002",
        "end_time": "2026-01-01T10:30:00Z",
        "is_active": True,
        "is_recurring": False,
        "notes": "Team meeting",
        "start_time": "2026-01-01T10:00:00Z"
    }
)
response.raise_for_status()
data = response.json()
```

```ruby
require "httparty"
require "json"
require "securerandom"

response = HTTParty.post(
  "https://api.carebit.co/v1/availability_periods",
  headers: {
    "Authorization" => "Bearer #{ENV.fetch("CAREBIT_ACCESS_TOKEN")}",
    "Idempotency-Key" => SecureRandom.uuid,
    "Content-Type" => "application/json"
  },
  body: {
    "availability_type" => "unavailability",
    "clinician_id" => "00000000-0000-4000-8000-000000000002",
    "end_time" => "2026-01-01T10:30:00Z",
    "is_active" => true,
    "is_recurring" => false,
    "notes" => "Team meeting",
    "start_time" => "2026-01-01T10:00:00Z"
  }.to_json
)
raise "Carebit API error: #{response.code}" unless response.success?
data = response.parsed_response
```

```php
<?php

$client = new GuzzleHttp\Client();

$response = $client->post("https://api.carebit.co/v1/availability_periods", [
    "headers" => [
      "Authorization" => "Bearer " . getenv("CAREBIT_ACCESS_TOKEN"),
      "Idempotency-Key" => bin2hex(random_bytes(16)),
    ],
    "json" => [
      "availability_type" => "unavailability",
      "clinician_id" => "00000000-0000-4000-8000-000000000002",
      "end_time" => "2026-01-01T10:30:00Z",
      "is_active" => true,
      "is_recurring" => false,
      "notes" => "Team meeting",
      "start_time" => "2026-01-01T10:00:00Z"
    ]
]);
$data = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);
```
