# API: Scheduling

| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | `/v1/booking-report` | Bookings per campaign, matched and unmatched | `activities:read` |
| GET | `/v1/bookings` | Bookings (yours, or everyone's for owners) | `activities:read` |
| POST | `/v1/bookings` | Book a time for someone (re-checked against the host's calendar) | `activities:write` |
| PATCH | `/v1/bookings/:id/attribution` | Count a booking for another campaign (or none) | `activities:write` |
| POST | `/v1/bookings/:id/cancel` | Cancel a booking (its host): the calendar event is removed and the attendee told | `activities:write` |
| POST | `/v1/bookings/:id/no-show` | Mark a booking as a no-show (its host): the attendee gets the reschedule email, and the event type's no-show sequence enrolls them | `messages:send` |
| GET | `/v1/event-types` | Event types (booking pages) | `activities:read` |
| POST | `/v1/event-types` | Create an event type: duration, buffers, notice, hosts (one, a round-robin queue, or a group), questions, branding, reminders | `activities:write` |
| PATCH | `/v1/event-types/:id` | Change an event type | `activities:write` |
| GET | `/v1/event-types/:id/slots` | Open times (from each host's calendar free/busy, working hours, buffers, notice and caps) | `activities:read` |
| GET | `/v1/holds` | Your calendar holds and their states | `activities:read` |
| POST | `/v1/holds` | Hold a time on your calendar with a drafted invite (sent when you approve it; released after 48 hours otherwise) | `activities:write` |
| POST | `/v1/holds/:id/release` | Release a hold | `activities:write` |
| GET | `/v1/public/book/:org/:slug` | A booking page: what it is and its open times for the next week (no sign-in) | — |
| POST | `/v1/public/book/:org/:slug` | Book a time on a booking page (no sign-in) | — |
| GET | `/v1/public/bookings/:id` | A booking seen through its manage link (when, and the page to pick another time) (no sign-in) | — |
| POST | `/v1/public/bookings/:id/cancel` | Cancel a booking with its manage link (no sign-in) | — |
| POST | `/v1/public/bookings/:id/confirm` | Confirm you're coming, with the booking's manage link (no sign-in) | — |
| PUT | `/v1/settings/booking-webhooks` | Set the signing secrets for Calendly and Cal.com booking webhooks (owners, signed in) (web app only) | `integrations:write` |
| POST | `/v1/webhooks/booking/:provider/:org` | A Calendly or Cal.com booking webhook (signed) (no sign-in) | — |

## Examples

### GET /v1/booking-report

Bookings per campaign, matched and unmatched

```bash
curl -s "https://api.closefinch.com/v1/booking-report" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/booking-report`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/bookings

Bookings (yours, or everyone's for owners)

```bash
curl -s "https://api.closefinch.com/v1/bookings" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/bookings`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/bookings

Book a time for someone (re-checked against the host's calendar)

```bash
curl -s -X POST "https://api.closefinch.com/v1/bookings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/bookings`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### PATCH /v1/bookings/$ID/attribution

Count a booking for another campaign (or none)

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/bookings/$ID/attribution" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/bookings/${id}/attribution`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/bookings/$ID/cancel

Cancel a booking (its host): the calendar event is removed and the attendee told

```bash
curl -s -X POST "https://api.closefinch.com/v1/bookings/$ID/cancel" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/bookings/${id}/cancel`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/bookings/$ID/no-show

Mark a booking as a no-show (its host): the attendee gets the reschedule email, and the event type's no-show sequence enrolls them

```bash
curl -s -X POST "https://api.closefinch.com/v1/bookings/$ID/no-show" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/bookings/${id}/no-show`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/event-types

Event types (booking pages)

```bash
curl -s "https://api.closefinch.com/v1/event-types" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/event-types`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/event-types

Create an event type: duration, buffers, notice, hosts (one, a round-robin queue, or a group), questions, branding, reminders

```bash
curl -s -X POST "https://api.closefinch.com/v1/event-types" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/event-types`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### PATCH /v1/event-types/$ID

Change an event type

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/event-types/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/event-types/${id}`, {
  method: "PATCH",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/event-types/$ID/slots

Open times (from each host's calendar free/busy, working hours, buffers, notice and caps)

```bash
curl -s "https://api.closefinch.com/v1/event-types/$ID/slots" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/event-types/${id}/slots`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/holds

Your calendar holds and their states

```bash
curl -s "https://api.closefinch.com/v1/holds" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/holds`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/holds

Hold a time on your calendar with a drafted invite (sent when you approve it; released after 48 hours otherwise)

```bash
curl -s -X POST "https://api.closefinch.com/v1/holds" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/holds`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/holds/$ID/release

Release a hold

```bash
curl -s -X POST "https://api.closefinch.com/v1/holds/$ID/release" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/holds/${id}/release`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/public/book/$ORG/$SLUG

A booking page: what it is and its open times for the next week. No sign-in, so it sends no key.

```bash
curl -s "https://api.closefinch.com/v1/public/book/$ORG/$SLUG"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/public/book/${org}/${slug}`, {
  method: "GET",
});
const data = await res.json();
```

### POST /v1/public/book/$ORG/$SLUG

Book a time on a booking page. No sign-in, so it sends no key.

```bash
curl -s -X POST "https://api.closefinch.com/v1/public/book/$ORG/$SLUG" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/public/book/${org}/${slug}`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/public/bookings/$ID

A booking seen through its manage link (when, and the page to pick another time). No sign-in, so it sends no key.

```bash
curl -s "https://api.closefinch.com/v1/public/bookings/$ID"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/public/bookings/${id}`, {
  method: "GET",
});
const data = await res.json();
```

### POST /v1/public/bookings/$ID/cancel

Cancel a booking with its manage link. No sign-in, so it sends no key.

```bash
curl -s -X POST "https://api.closefinch.com/v1/public/bookings/$ID/cancel" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/public/bookings/${id}/cancel`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/public/bookings/$ID/confirm

Confirm you're coming, with the booking's manage link. No sign-in, so it sends no key.

```bash
curl -s -X POST "https://api.closefinch.com/v1/public/bookings/$ID/confirm" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/public/bookings/${id}/confirm`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

Request and response schemas: [https://www.closefinch.com/openapi.json](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
