# Quickstart: your first booking in 10 minutes – Tiempo

> Create a business, add two barbers with working hours, find open times, hold a slot, confirm it, and watch Tiempo refuse a double booking. curl only.

Source: https://tiempo.one/docs/quickstart

You’ll set up a barbershop with two barbers, find their open times, hold a slot while a customer pays, confirm it, and see Tiempo refuse a second booking for the same chair. Everything here runs in test mode with plain HTTP, so it works from any language.

[Create a platform](https://tiempo.one/signup) to get a test key (`tpt_…`). It’s shown once, so copy it. Then set three variables in your shell; you’ll fill in `ACCOUNT` in the first step.

Shell

```bash
export TIEMPO=https://api.tiempo.one
export TIEMPO_KEY=tpt_…   # from sign-up
export ACCOUNT=           # from step 1
```

## 1. Add a business

Each business on your platform is an **account**. Its timezone is where “Monday 09:00” is measured. Copy the `id` into `ACCOUNT`: every request about this business sends it in the `Tiempo-Account` header.

Create the account

```bash
curl -X POST "$TIEMPO/v1/accounts" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Fade Street Barbers",
    "timezone": "Europe/London"
  }'
```

## 2. Add the barbers

Anything that can be booked is a **resource**: a barber, a chair, a room, a court. The `type` is yours to name. Create Ann and Bob and note their ids.

Create a resource (run twice)

```bash
curl -X POST "$TIEMPO/v1/resources" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Tiempo-Account: $ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ann",
    "type": "barber"
  }'
```

## 3. Give them working hours

A **schedule** is a weekly pattern of local times, starting on a date. Lunch breaks are just gaps between intervals; a list of several weeks makes a rota. Days off and holidays are [blocks](https://tiempo.one/docs/blocks); one-off changes are [overrides](https://tiempo.one/docs/schedule-overrides). A resource with no schedule is closed: hours are what make it bookable.

Monday to Saturday, 9 to 5 (for each barber)

```bash
curl -X POST "$TIEMPO/v1/schedules" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Tiempo-Account: $ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "res_ann…",
    "effective_from": "2026-11-01",
    "weeks": [
      {
        "monday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ],
        "tuesday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ],
        "wednesday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ],
        "thursday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ],
        "friday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ],
        "saturday": [
          {
            "start": "09:00",
            "end": "17:00"
          }
        ]
      }
    ]
  }'
```

## 4. Find open times

Ask for 45 minutes with _either_ barber. Tiempo returns every start time on a 15-minute grid where someone is free, with who. Your app shows these; it never works out availability itself.

Search

```bash
curl -X POST "$TIEMPO/v1/availability" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Tiempo-Account: $ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "2026-11-16T00:00:00Z",
    "to": "2026-11-17T00:00:00Z",
    "timezone": "Europe/London",
    "segments": [
      {
        "resources": [
          "res_ann…",
          "res_bob…"
        ],
        "duration_minutes": 45
      }
    ]
  }'
```

Response (first slot)

```json
{
  "object": "availability",
  "slots": [
    { "start": "2026-11-16T09:00:00Z", "end": "2026-11-16T09:45:00Z",
      "segments": [{ "resources": ["res_ann…", "res_bob…"] }] },
    …
  ]
}
```

## 5. Hold the slot

Creating a booking without a status places a **hold**: `pending`, with an `expires_at` 15 minutes away. It occupies the barber while your customer pays. Giving `resources` means “whichever is free, in this order”, and Tiempo picks atomically, so two customers can’t both get Ann.

Send an `Idempotency-Key` on every POST. If the network drops and you retry, you get the same booking back instead of a second one.

Hold

```bash
curl -X POST "$TIEMPO/v1/bookings" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Tiempo-Account: $ACCOUNT" \
  -H "Idempotency-Key: apt_123-hold" \
  -H "Content-Type: application/json" \
  -d '{
    "segments": [
      {
        "resources": [
          "res_ann…",
          "res_bob…"
        ],
        "start": "2026-11-16T09:00:00Z",
        "end": "2026-11-16T09:45:00Z"
      }
    ],
    "metadata": {
      "appointment_id": "apt_123"
    }
  }'
```

## 6. Confirm it

When payment succeeds, confirm. If the customer walks away, do nothing: the hold expires, the time frees up, and you get a `booking.expired` webhook. To book with no hold, send `"status": "confirmed"` when creating.

Confirm

```bash
curl -X POST "$TIEMPO/v1/bookings/bkg_…/confirm" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Tiempo-Account: $ACCOUNT"
```

## 7. Try to double-book

Book the same barber at the same time again. Tiempo locks the barber while it checks, so this is refused even when two requests arrive in the same millisecond. A `409 booking_conflict` says why, per segment: offer the customer other times rather than retrying.

409 Conflict

```json
{
  "error": {
    "type": "conflict_error",
    "code": "booking_conflict",
    "message": "The requested time is not available.",
    "conflicts": [{
      "segment": 0,
      "resource": "res_ann…",
      "reason": "capacity_exceeded",
      "message": "Resource does not have enough free capacity during the period."
    }]
  }
}
```

## 8. Hear about changes

Every change is an event. Add one webhook endpoint for your whole platform and Tiempo POSTs each event to it, signed, retrying for about three days. Until your endpoint is live, read the same events from `/v1/events`.

Next: map your product onto Tiempo with a [use-case guide](https://tiempo.one/docs/salons-and-barbers), give your coding agent the [rules file](https://tiempo.one/docs/build-with-ai), or read the [bookings reference](https://tiempo.one/docs/bookings).

Add an endpoint (platform-wide)

```bash
curl -X POST "$TIEMPO/v1/webhook_endpoints" \
  -H "Authorization: Bearer $TIEMPO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example/webhooks/tiempo",
    "enabled_events": [
      "*"
    ]
  }'
```

Or read recent booking events

```bash
curl "$TIEMPO/v1/events?type=booking.*&limit=10" \
  -H "Authorization: Bearer $TIEMPO_KEY"
```

The machine-readable description is at [/openapi.json](https://tiempo.one/openapi.json). Try calls in [Swagger UI](https://tiempo.one/swagger-ui.html).[Tiempo home](https://tiempo.one/)[Dashboard](https://tiempo.one/app)
