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

# Slog API

Slog is a headless project management system accessible via REST API and the Model Context Protocol (MCP).

## Base URL

```
http://slog.ai
```

## Authentication

All resource endpoints require authentication via an Oauth Bearer token or an API key.

### API key authentication

API keys are automatically created by the CLI. They can also be used using the `/api-keys` endpoints to create additional keys with custom names and expiration dates. To authenticate with an API key include it in the `Authorization` header, e.g.

```
Authorization: Basic sk_abc123
```

This can most easily be done using `curl`. The colon after the key prevents `curl` from prompting for a password as well.

```bash theme={null}
curl https://slog.ai/tasks -u sk_abc123:
```

The API key can also be included in the `Slog-Api-Key` header:

```http theme={null}
Slog-Api-Key: <key>
```

### Oauth authentication

Oauth tokens are generally created and handled by other services. If you have a token you can use it directly for API calls using the `Authorization` header:

```http theme={null}
Authorization: Bearer <token>
```

## Response Format

Single resources are wrapped in a key matching the resource type. Lists use the plural name with a `pagination` object.

```json theme={null}
{ "task": { "id": "...", "title": "..." } }
```

```json theme={null}
{
  "tasks": [...],
  "pagination": { "limit": 50, "nextCursor": "task_01jq..." }
}
```

Errors always use this shape:

```json theme={null}
{ "error": { "message": "Field \"foo\" is not filterable" } }
```

## Resources

| Resource                 | Description                                                           |
| ------------------------ | --------------------------------------------------------------------- |
| [Tasks](tasks)           | Primary unit of work                                                  |
| [Projects](projects)     | Groups tasks together                                                 |
| [Teams](teams)           | Organizational unit; defines task reference prefixes (e.g. `PLAT-42`) |
| [Milestones](milestones) | Time-boxed goals                                                      |

## Query Parameters

All list endpoints support the following query parameters.

### Field Selection

Request only the fields you need. Nested relations use brace notation.

```
GET /tasks?fields=id,identifier,title,assignee{id,name}
```

If omitted, each resource returns a minimal default set (e.g. `id`, `identifier`, `title`, `status` for tasks).

### Return a single record by ID or reference

```
GET /tasks/123
GET /tasks/PLAT-123
```

### Filtering

Filters use the form `filter[op][field]=value`.

| Operator     | Description                          |
| ------------ | ------------------------------------ |
| `eq`         | Exact match                          |
| `neq`        | Not equal                            |
| `gt` / `gte` | Greater than / greater than or equal |
| `lt` / `lte` | Less than / less than or equal       |
| `contains`   | Case-insensitive substring           |
| `startsWith` | Case-insensitive prefix              |
| `in`         | Match any of a comma-separated list  |

Multiple filters are combined with AND:

```
GET /tasks?filter[eq][status]=TODO&filter[gte][dueDate]=2026-01-01
GET /tasks?filter[in][status]=TODO,IN_PROGRESS
GET /tasks?filter[contains][title]=auth
```

Only fields marked as filterable for a given resource can be filtered. See each resource's field table.

### Sorting

Sorts use the form `sort[field]=direction`. Multiple sorts are applied in order.

```
GET /tasks?sort[dueDate]=asc&sort[priority]=desc
```

Only fields marked as sortable can be sorted.

### Pagination

All list endpoints use cursor-based pagination.

| Parameter | Default | Max   | Description                                |
| --------- | ------- | ----- | ------------------------------------------ |
| `limit`   | `50`    | `250` | Number of results per page                 |
| `cursor`  | —       | —     | ID of the last item from the previous page |

```
GET /tasks?limit=20
GET /tasks?limit=20&cursor=task_01jq...
```

The response `pagination.nextCursor` is `null` when there are no more pages.

## Batch Requests

Fetch multiple resources in a single round-trip.

```http theme={null}
POST /batch
Content-Type: application/json

{
  "requests": [
    "/tasks?fields=id,title,status&limit=10",
    "/tasks/PLAT-42?fields=id,title,description,assignee{name}",
    "/projects/proj_01jq.../milestones"
  ]
}
```

Response:

```json theme={null}
{
  "results": [
    { "tasks": [...], "pagination": { "limit": 10, "nextCursor": null } },
    { "task": { "id": "...", "title": "...", "description": "...", "assignee": { "name": "..." } } },
    { "milestones": [...], "pagination": { "limit": 50, "nextCursor": null } }
  ]
}
```

Each result corresponds to the request at the same index. If an individual request fails, that slot contains `{ "error": { "message": "...", "code": "..." } }` and the rest still succeed.

Batch supports GET-style requests only (list, get, list sub-resource).

## IDs and Identifiers

Every record has an `id` (a sortable UPID string, e.g. `task_01jq...`). Tasks additionally have a human-readable `identifier` generated from the team prefix and an incrementing sequence number (e.g. `PLAT-42`).

The `GET /tasks/:id` endpoint accepts either format:

```
GET /tasks/task_01jqabcdef...
GET /tasks/PLAT-42
```

## Authentication Endpoints

These endpoints are outside the main resource router and do not require a pre-existing token.

### OAuth

```
GET /auth/google          Redirect to Google OAuth
GET /auth/google/callback
GET /auth/github          Redirect to GitHub OAuth
GET /auth/github/callback
```

On success the callback redirects with a JWT:

```json theme={null}
{ "data": { "token": "eyJ...", "user": { "id": "...", "name": "...", "email": "..." } } }
```

### Current User

```
GET /auth/me
Authorization: Bearer <token>
```

```json theme={null}
{ "data": { "user": { "id": "...", "name": "...", "email": "..." } } }
```

### Logout

```
POST /auth/logout
Authorization: Bearer <token>
```

Returns `204 No Content`.

## API Key Endpoints

API keys allow programmatic access without OAuth. They are created per-user and scoped to your account.

### List Keys

```
GET /api-keys
Authorization: Bearer <token>
```

```json theme={null}
{
  "data": [
    {
      "id": "key_01jq...",
      "name": "CI pipeline",
      "prefix": "sl_abc",
      "lastUsedAt": "2026-04-25T10:00:00Z",
      "expiresAt": null,
      "createdAt": "2026-01-01T00:00:00Z"
    }
  ]
}
```

Full key values are never returned after creation.

### Create Key

```
POST /api-keys
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "CI pipeline",
  "expiresAt": "2027-01-01T00:00:00Z"
}
```

`expiresAt` is optional. The full key is returned only in this response:

```json theme={null}
{
  "data": {
    "key": "sl_abc.secretpart...",
    "prefix": "sl_abc",
    "name": "CI pipeline"
  }
}
```

### Delete Key

```
DELETE /api-keys/:id
Authorization: Bearer <token>
```

Returns `204 No Content`.
