---
source: CrewKit documentation
url: https://crewkit.io/docs/api-overview.md
title: "API Overview"
description: "Base URL, authentication, pagination, rate limits, and error handling."
---


The crewkit API is a JSON REST API. All endpoints are under `/api/v1/`.

---

## Base URL

| Environment | URL |
|-------------|-----|
| Production | `https://api.crewkit.io/api/v1` |

For local development and testing, set the `CREWKIT_API_URL` environment variable.

---

## Authentication

All API requests (except auth endpoints and health checks) require a Bearer token:

```
Authorization: Bearer <access_token>
```

Access tokens expire after 4 hours. Use the refresh token to get a new one. See [Authentication](/docs/authentication) for the full flow.

---

## Request format

Send JSON bodies with `Content-Type: application/json`:

```bash
curl -X POST https://api.crewkit.io/api/v1/auth/device \
  -H "Content-Type: application/json"
```

---

## Response format

Successful responses return JSON with a `data` key (or resource-specific key):

```json
{
  "data": { ... },
  "meta": {
    "current_page": 1,
    "total_pages": 5,
    "total_count": 123
  }
}
```

---

## Resource IDs

All API responses use UUID v4 for resource identifiers. These are exposed via the `id` field in responses and used in URL paths:

```
GET /api/v1/:org_id/sessions/432e16a3-0bf4-4117-8ee0-9a3b21ebe07b
```

---

## Pagination

List endpoints support cursor-based pagination:

| Parameter | Description | Default |
|-----------|-------------|---------|
| `page` | Page number | 1 |
| `per_page` | Items per page | 25 |

Pagination metadata is included in the `meta` key of the response.

---

## Rate limits

| Scope | Limit |
|-------|-------|
| Per organization | 1,000 requests/hour |
| Per IP address | 100 requests/minute |

Rate limit headers are included in every response:

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1697040000
```

---

## Error format

Errors return a JSON body with an `error` key:

```json
{
  "error": "Validation failed: Name can't be blank",
  "details": {
    "name": ["can't be blank"]
  }
}
```

### HTTP status codes

| Code | Meaning |
|------|---------|
| `200` | Success |
| `201` | Created |
| `400` | Bad request — missing or invalid parameters |
| `401` | Unauthorized — missing or invalid token |
| `403` | Forbidden — insufficient permissions |
| `404` | Not found |
| `422` | Unprocessable entity — validation error |
| `429` | Too many requests — rate limited |
| `500` | Internal server error |

---

## Organization-scoped routes

Most endpoints are scoped to an organization. The organization ID appears in the URL path:

```
GET /api/v1/:org_id/sessions
GET /api/v1/:org_id/projects
```

Replace `:org_id` with your organization's external ID (UUID).

---

## Next steps

- [Authentication](/docs/authentication)
- [Sessions API](/docs/api-sessions)
