> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.slotflow.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.slotflow.dev/_mcp/server.

# Create a booking

POST https://api.slotflow.dev/v1/bookings
Content-Type: application/json

Create a booking for a specific time slot. The API validates that:

1. The human exists and is active
2. The duration matches one of the human's allowed `meeting_durations`
3. The time slot falls within working hours (or is covered by an open override)
4. No schedule block overrides conflict with the slot
5. No existing confirmed booking occupies the slot

If another booking was created for the same slot between your agent's slot query and this request, you'll receive a `409 SLOT_UNAVAILABLE` error. Your agent should retry with the next available slot.

**Metadata** — pass arbitrary JSON (lead IDs, conversation IDs, ticket numbers) that your agent needs to maintain workflow context. This metadata is included in webhook payloads.

**Plan limits** — bookings count toward your monthly limit. On paid plans with auto-purchase enabled, overage packs ($19 per 500 bookings) are charged automatically when the limit is reached.


Reference: https://docs.slotflow.dev/api-reference/slotflow-api/bookings/create-booking

## Authentication

- `Authorization` header (bearer token, required) — API key authentication. Pass your key as a Bearer token: ``` Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx ``` Get your API key from the [Slotflow Dashboard](https://app.slotflow.dev).

## Request

### Body (application/json)

This endpoint expects a CreateBookingRequest.

- `human_id` (string, required) — ID of the human to book
- `starts_at` (datetime, required) — Booking start time in ISO 8601 UTC format
- `duration` (integer, required) — Meeting duration in minutes. Must match one of the human's meeting_durations.
- `attendee_name` (string, required) — Name of the person being booked
- `attendee_email` (string, optional) — Email of the attendee (optional)
- `metadata` (map from string to any, optional) — Arbitrary JSON for your agent's workflow state (lead IDs, conversation IDs, etc.)

## Response

### 201

Booking confirmed

- `id` (string, optional)
- `human_id` (string, optional)
- `starts_at` (datetime, optional) — Booking start time in UTC
- `ends_at` (datetime, optional) — Booking end time in UTC
- `duration_minutes` (integer, optional) — Duration in minutes
- `attendee_name` (string, optional) — Name of the person being booked
- `attendee_email` (string, optional, nullable) — Email of the attendee (optional)
- `status` (enum, optional)
  - Allowed values: `confirmed`, `cancelled`
- `metadata` (map from string to any, optional) — Arbitrary JSON metadata passed by your agent for workflow tracking
- `created_at` (datetime, optional)

## Errors

### 402 Payment Required Error

Plan limit reached

- `error` (ApiErrorError, optional)

### 404 Not Found Error

Resource not found

- `error` (ApiErrorError, optional)

### 409 Conflict Error

Slot already booked

- `error` (ApiErrorError, optional)

### 422 Unprocessable Entity Error

Validation, duration, or scheduling error

- `error` (ApiErrorError, optional)

## Types

### ApiErrorError

- `code` (enum, optional) — Machine-readable error code
  - Allowed values: `UNAUTHORIZED`, `NOT_FOUND`, `SLOT_UNAVAILABLE`, `INVALID_DURATION`, `OUTSIDE_WORKING_HOURS`, `SCHEDULE_BLOCKED`, `LIMIT_REACHED`, `VALIDATION_ERROR`
- `message` (string, optional) — Human-readable error description
- `status` (integer, optional) — HTTP status code

## Examples

**Request**

```json
{
  "human_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "starts_at": "2026-03-10T14:00:00.000Z",
  "duration": 30,
  "attendee_name": "Alex Rivera",
  "attendee_email": "alex@startup.io",
  "metadata": {
    "lead_id": "lead_8294",
    "conversation_id": "conv_1847",
    "source": "ai_sdr"
  }
}
```

**Response**

```json
{
  "id": "b9e4f2a1-3c5d-4e6f-8a9b-0c1d2e3f4a5b",
  "human_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "starts_at": "2026-03-10T14:00:00.000Z",
  "ends_at": "2026-03-10T14:30:00.000Z",
  "duration_minutes": 30,
  "attendee_name": "Alex Rivera",
  "attendee_email": "alex@startup.io",
  "status": "confirmed",
  "metadata": {
    "lead_id": "lead_8294",
    "conversation_id": "conv_1847",
    "source": "ai_sdr"
  },
  "created_at": "2026-03-10T10:00:00.000Z"
}
```

**SDK Code**

```python Bookings_createBooking_example
import requests

url = "https://api.slotflow.dev/v1/bookings"

payload = {
    "human_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "starts_at": "2026-03-10T14:00:00.000Z",
    "duration": 30,
    "attendee_name": "Alex Rivera",
    "attendee_email": "alex@startup.io",
    "metadata": {
        "lead_id": "lead_8294",
        "conversation_id": "conv_1847",
        "source": "ai_sdr"
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Bookings_createBooking_example
const url = 'https://api.slotflow.dev/v1/bookings';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"human_id":"f47ac10b-58cc-4372-a567-0e02b2c3d479","starts_at":"2026-03-10T14:00:00.000Z","duration":30,"attendee_name":"Alex Rivera","attendee_email":"alex@startup.io","metadata":{"lead_id":"lead_8294","conversation_id":"conv_1847","source":"ai_sdr"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Bookings_createBooking_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.slotflow.dev/v1/bookings"

	payload := strings.NewReader("{\n  \"human_id\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\",\n  \"starts_at\": \"2026-03-10T14:00:00.000Z\",\n  \"duration\": 30,\n  \"attendee_name\": \"Alex Rivera\",\n  \"attendee_email\": \"alex@startup.io\",\n  \"metadata\": {\n    \"lead_id\": \"lead_8294\",\n    \"conversation_id\": \"conv_1847\",\n    \"source\": \"ai_sdr\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Bookings_createBooking_example
require 'uri'
require 'net/http'

url = URI("https://api.slotflow.dev/v1/bookings")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"human_id\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\",\n  \"starts_at\": \"2026-03-10T14:00:00.000Z\",\n  \"duration\": 30,\n  \"attendee_name\": \"Alex Rivera\",\n  \"attendee_email\": \"alex@startup.io\",\n  \"metadata\": {\n    \"lead_id\": \"lead_8294\",\n    \"conversation_id\": \"conv_1847\",\n    \"source\": \"ai_sdr\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java Bookings_createBooking_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.slotflow.dev/v1/bookings")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"human_id\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\",\n  \"starts_at\": \"2026-03-10T14:00:00.000Z\",\n  \"duration\": 30,\n  \"attendee_name\": \"Alex Rivera\",\n  \"attendee_email\": \"alex@startup.io\",\n  \"metadata\": {\n    \"lead_id\": \"lead_8294\",\n    \"conversation_id\": \"conv_1847\",\n    \"source\": \"ai_sdr\"\n  }\n}")
  .asString();
```

```php Bookings_createBooking_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.slotflow.dev/v1/bookings', [
  'body' => '{
  "human_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "starts_at": "2026-03-10T14:00:00.000Z",
  "duration": 30,
  "attendee_name": "Alex Rivera",
  "attendee_email": "alex@startup.io",
  "metadata": {
    "lead_id": "lead_8294",
    "conversation_id": "conv_1847",
    "source": "ai_sdr"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Bookings_createBooking_example
using RestSharp;

var client = new RestClient("https://api.slotflow.dev/v1/bookings");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"human_id\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\",\n  \"starts_at\": \"2026-03-10T14:00:00.000Z\",\n  \"duration\": 30,\n  \"attendee_name\": \"Alex Rivera\",\n  \"attendee_email\": \"alex@startup.io\",\n  \"metadata\": {\n    \"lead_id\": \"lead_8294\",\n    \"conversation_id\": \"conv_1847\",\n    \"source\": \"ai_sdr\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Bookings_createBooking_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "human_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "starts_at": "2026-03-10T14:00:00.000Z",
  "duration": 30,
  "attendee_name": "Alex Rivera",
  "attendee_email": "alex@startup.io",
  "metadata": [
    "lead_id": "lead_8294",
    "conversation_id": "conv_1847",
    "source": "ai_sdr"
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.slotflow.dev/v1/bookings")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```