> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roofkit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Partner API

> Call the RoofKit Partner API v1 from your server with a workspace API key.

Use the Partner API when an external system needs authenticated, workspace-scoped server-to-server access to RoofKit. CRMs, forms, schedulers, and agencies use it to sync leads, read attribution, order roof reports, and create roof renders.

AI clients that act for a signed-in workspace member use [RoofKit MCP](https://docs.roofkit.ai/mcp-server.md) instead. MCP uses OAuth, not API keys.

## Base URL and authentication

Every endpoint is under `https://api.roofkit.ai/api/v1`. Send a workspace API key as a Bearer token on each request.

```bash Verify the API key theme={null}
curl https://api.roofkit.ai/api/v1/me \
  -H "Authorization: Bearer rk_live_your_api_key"
```

[Verify API key](https://docs.roofkit.ai/api-reference/foundation/verify-api-key.md) returns the key and the workspace that it belongs to.

> [card] [API keys](https://app.roofkit.ai/settings/api-keys)
>
> Create and manage keys in workspace settings. Keep keys on your server and rotate them when ownership changes.

> [card] [OpenAPI document](https://api.roofkit.ai/api/v1/openapi.json)
>
> Download the OpenAPI 3.1 contract that this reference is built from.

## Contract

RoofKit Partner API v1 authenticates requests with workspace API keys. API keys bind each request to exactly one workspace; Partner API paths do not accept roofer\_id, workspace\_id, or tenant identifiers. Authenticated endpoints are limited to 60 requests per minute per API key, method, and route template; invalid authentication attempts are limited separately at 20 requests per minute per client and endpoint. Date-time parameters and fields accept ISO 8601 with Z or a ±HH:MM offset, for example 2026-09-07T04:00:00Z or 2026-09-07T00:00:00-04:00. Both name the same instant and return the same result. Encode + as %2B in a query string. Responses return UTC.

A date-time without an offset, for example 2026-09-07T04:00:00, is deprecated. Until the sunset on 2027-01-10T00:00:00Z it is read as UTC, and the response carries a `Deprecation` header (RFC 9745) and a `Sunset` header (RFC 8594). From the sunset, Z or a ±HH:MM offset is required. A date-time without an offset then returns 400 with the `VALIDATION_ERROR` code, and the response carries no `Deprecation` or `Sunset` header.

Each API key holds only the scopes that a workspace owner or admin chose when the key was created, and its scopes never change. Each operation lists the scopes it requires in `x-required-scopes`. A new key in Settings starts on the Read-only preset: `leads.read`, `analytics.read`, `reports.read`, and `data_objects.read`. A Read-only key can call every read operation except exports, Sales Visualizer reads, and trashed Data Objects, and it cannot call any write operation. A call that needs a scope the key does not hold returns 403 `FORBIDDEN`, and `error.details.required_scope` names a missing scope.

## Errors

Every error returns the same body. `code` is stable. Use `request_id` when you contact support.

```json Error body theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request payload, query, or required header is invalid.",
    "request_id": "6f1c2a9e-4b7d-4c1e-9a53-2d8e0f7b3c41"
  }
}
```

| Code | Status | Meaning |
| - | - | - |
| `UNAUTHORIZED` | 401 | The API key is missing, invalid, or revoked. |
| `FORBIDDEN` | 403 | The key does not hold a scope that the endpoint needs. `details.required_scope` names it. |
| `NOT_FOUND` | 404 | The resource does not exist in the workspace of the key. |
| `CONFLICT` | 409, 410 | The request conflicts with an idempotency key or an external event identity, or the resource is gone. |
| `VALIDATION_ERROR` | 400, 411, 413 | The payload, a query parameter, or a required header is not valid. |
| `INSUFFICIENT_CREDITS` | 402 | The workspace does not have the credits that the operation uses. |
| `RATE_LIMITED` | 429 | Wait for the time in `Retry-After`, then send the request again. |
| `INTERNAL_ERROR` | 500, 503 | RoofKit could not finish the request. Retry it later with the same `Idempotency-Key`. |

`details` is optional. Each endpoint page lists the statuses that it returns.

## Pagination

Cursor-paged list endpoints take `limit` and `cursor`, and return a `pagination` object with `limit`, `next_cursor`, and `has_more`. Send `next_cursor` as `cursor` to read the next page. Stop when `has_more` is `false`. Each endpoint page shows its own limits.

## Try it out

Each endpoint page has a playground. It sends the request from your browser straight to `api.roofkit.ai`, so your API key does not pass through the docs host.

> [!WARNING]
>
> **Requests change real data**
>
> The playground calls the live API with your key. Write endpoints create, update, and bill in your workspace. Use a key from a test workspace when you try write endpoints.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.