# API and sign-in

Call the Auto Lab API with a personal access key or a service account, and let your own app sign people in with their Auto Lab account.

Canonical page: https://app.auto-lab.ai/docs/developers/api

The Auto Lab web app and CLI talk to a REST API. You can call the same API from a script, a CI job or your own backend. You can also let your own app sign people in with their Auto Lab account and act for them.

## Base URL and keys

The API's base URL is `https://api.auto-lab.ai/v1`. Send a key in the `Authorization` header:

```text
Authorization: Bearer <key>
```

The API uses its own names in routes and fields. It calls a goal a **project** and an organization an **account**.

| Key | Starts with | Acts as | Where it comes from |
| --- | --- | --- | --- |
| Personal access key | `kortix_pat_` | You | **Personal settings › Personal access keys** |
| Service account token | `kortix_sa_` | The service account itself | **Organization settings › API keys** |
| OAuth access token | `kortix_oat_` | The person who signed in to your app | [Sign in with Auto Lab](#sign-in-with-auto-lab) |

## Personal access key

A personal access key acts as you. It can do exactly what you can do in Auto Lab, and nothing more. If your role changes, the key's reach changes with it. If you leave the organization, the key stops working.

1. Open **Personal settings › Personal access keys** and select **New key**.
2. Enter a **Name** that says where you will use the key, such as "Nightly report job".
3. Pick a **Scope**: the whole organization, or one goal. A key for one goal cannot reach any other goal.
4. Pick when it **Expires**. Your organization can require every key to expire.
5. Select **Create key**, then copy the key. Auto Lab shows it only once.

To stop a key, open its row menu and select **Revoke key**. It stops working at once. The CLI's `kortix login` creates a key of this kind for you (see [CLI](/docs/developers/cli#sign-in)).

## Service account

A service account is an identity of its own, for automation that should keep working after the person who set it up leaves. Organization owners and admins create one in **Organization settings › API keys**. Its token is shown once.

A new service account has no access at all, and every call it makes returns `403` until you give it a role. Grant it one on each goal it needs, for example with the CLI:

```sh
kortix access grant --service-account <service-account-id> --role member --project <goal-id>
```

## Make a request

Check who a key belongs to and which organizations it can see:

```sh
curl -s https://api.auto-lab.ai/v1/accounts/me \
  -H "Authorization: Bearer $AUTOLAB_API_KEY"
```

The answer holds your `user_id`, your `email` and an `accounts` list, one entry per organization with its `account_id`, `slug`, `name` and your `role`.

List the goals you can read in one organization:

```sh
curl -s "https://api.auto-lab.ai/v1/projects?account_id=$ACCOUNT_ID" \
  -H "Authorization: Bearer $AUTOLAB_API_KEY"
```

The answer is a list of goals, each with its `project_id`, `name`, `default_branch` and `dashboard_url`. Without `account_id`, the API uses your default organization.

Some routes you may want next:

| Route | What it returns |
| --- | --- |
| `GET /v1/projects/{projectId}` | One goal. |
| `GET /v1/projects/{projectId}/outcome` | The goal's objective, what it tracks, and its delegation level. |
| `GET /v1/projects/{projectId}/tasks` | The goal's task board. |
| `GET /v1/projects/{projectId}/change-requests` | The goal's change requests. |

A `401` means the key is missing, wrong, expired or revoked. A `403` means the key works but its owner is not allowed to do that.

## API reference

The full reference is at [api.auto-lab.ai/v1/docs](https://api.auto-lab.ai/v1/docs). The raw OpenAPI document is at `https://api.auto-lab.ai/v1/openapi.json`. Both are generated from the API's code, so they use the API's names and list some routes Auto Lab does not use. Auto Lab does not publish an SDK; call the API directly.

## Sign in with Auto Lab

Your own app, such as an internal dashboard or a partner portal, can let people sign in with their Auto Lab account. The app then acts as the person who signed in, with that person's permissions and no more. Auto Lab is a standard OAuth 2.1 authorization server: authorization code flow with PKCE.

### Register your app

Organization owners and admins register apps in **Organization settings › API keys**, under **OAuth apps**. Select **Register app** and fill in:

| Field | What to enter |
| --- | --- |
| **Name** | The name people see on the consent page. |
| **Description** | Optional. |
| **Type** | **Confidential** for a server-side app, which gets a client secret. **Public** for a browser or native app, which has no secret and relies on PKCE. You cannot change the type later. |
| **Redirect URIs** | One per line, up to 20. HTTPS, except on a loopback address such as `localhost`. No `#fragment`. Auto Lab matches them character for character. |
| **Scopes** | The most the app may ask for. Each sign-in can ask for fewer. |

Copy the client ID and, for a confidential app, the secret. The secret is shown only once. If you lose it, use **Rotate secret** from the app's row menu.

| Scope | What the app gets |
| --- | --- |
| `profile` | Who the person is: their ID, email and organization. |
| `email` | Their email address. |
| `kortix` | Acting as the person on the whole API, with their permissions. Without it, the token only identifies them. |

The `mcp:read` and `mcp:write` scopes belong to the [Auto Lab MCP server](/docs/developers/mcp) and work only there.

### Endpoints

| Endpoint | Address |
| --- | --- |
| Discovery | `https://api.auto-lab.ai/.well-known/oauth-authorization-server` |
| Authorize | `https://api.auto-lab.ai/v1/oauth/authorize` |
| Token | `https://api.auto-lab.ai/v1/oauth/token` |
| Revoke | `https://api.auto-lab.ai/v1/oauth/revoke` |
| User info | `https://api.auto-lab.ai/v1/oauth/userinfo` |

The discovery document follows RFC 8414. It is also served at `/v1/oauth/.well-known/oauth-authorization-server`. Auto Lab does not offer OpenID Connect discovery or ID tokens; read the person's identity from the user info endpoint.

### The sign-in flow

### Send the person to Auto Lab
Redirect the browser to the authorize endpoint with `response_type=code`, your `client_id`, one of your `redirect_uri` values, the `scope` you need, a random `state`, and a PKCE `code_challenge` with `code_challenge_method=S256`.

```text
https://api.auto-lab.ai/v1/oauth/authorize?response_type=code&client_id=<client-id>&redirect_uri=https%3A%2F%2Fapp.example.com%2Fauth%2Fcallback&scope=profile%20kortix&state=<state>&code_challenge=<challenge>&code_challenge_method=S256
```

### The person allows your app
The person signs in to Auto Lab and sees a consent page that names your app and what it asks for, with **Allow** and **Deny**. Auto Lab remembers an approval, so a later sign-in that asks for the same scopes goes straight back to your app. Auto Lab then redirects to your `redirect_uri` with `code` and `state`, or with `error=access_denied`.

### Exchange the code
Within five minutes, post the code to the token endpoint as a form. A confidential app sends its `client_secret`. A public app must not send one.

```sh
curl -s https://api.auto-lab.ai/v1/oauth/token \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri=https://app.example.com/auth/callback \
-d code_verifier="$CODE_VERIFIER" \
-d client_id="$CLIENT_ID" \
-d client_secret="$CLIENT_SECRET"
```

The answer holds an `access_token` (starting `kortix_oat_`), a `refresh_token` (starting `kortix_ort_`), `token_type` `Bearer`, `expires_in` of 3600 seconds, and the granted `scope`.

### Call the API as the person
Send the access token as a bearer token. With the `kortix` scope it works on every route, exactly like that person's own personal access key. `GET /v1/oauth/userinfo` returns their `sub`, `user_id`, `account_id` and `email`, and needs the `profile` or `email` scope.

### Refresh and sign out

Access tokens last one hour. To get a new one, post `grant_type=refresh_token`, the `refresh_token` and your client credentials to the token endpoint. Each refresh token works once and lasts 30 days. The answer carries a new pair, and the old access token stops working.

To sign someone out, post the `token` and your client credentials to the revoke endpoint. Revoking either token of a pair revokes both.

The token endpoint accepts 20 requests a minute per app.

### Manage the app

Each app's row menu in **Organization settings › API keys** has:

- **Edit app**, to change its details. Changes apply from the next sign-in, and tokens already issued keep working until they expire. Switch **Active** off here to stop new sign-ins without deleting the app.
- **Rotate secret**, to replace a lost or leaked secret.
- **Delete app**, to remove it and revoke every token it was given.
