---
title: "Authentication"
description: "API keys for the typeship API: how to create one, how to send it, and how it is stored."
url: https://typeship.dev/docs/typeship-api/api/authentication
markdown: https://typeship.dev/docs/typeship-api/api/authentication.md
section: "Get started"
---
> ## Documentation index
> Fetch the complete documentation index at https://typeship.dev/llms.txt (every page, one line each) or the full text at https://typeship.dev/llms-full.txt.
> Append .md to any docs URL, or send Accept: text/markdown, for the markdown twin of that page.

# Authentication

API keys for the typeship API: how to create one, how to send it, and how it is stored.

The typeship API authenticates with API keys. One key identifies one account. The same key works for the [typeship SDK](https://typeship.dev/docs/sdks), the [typeship CLI](https://typeship.dev/docs/cli), and the [typeship MCP server](https://typeship.dev/docs/typeship-api/mcp).

## Create a key

In the console under **api keys**, name the key and choose **create key**. The full key is shown once. Copy it then; afterwards the console shows the last four characters to tell keys apart.

Or let the [typeship CLI](https://typeship.dev/docs/cli) ask for one: `typeship login` opens the console's approval page, you approve `typeship CLI on <host>` for the active organization, and the API mints the key straight to that machine. The request carries a PKCE-style challenge; the key is handed only to the typeship CLI that proves the matching verifier, once, and never appears in the browser. Such keys are listed and revoked like any other.

Keys look like this:

```text
ak_7Q2KD4MZX9P1VN6TBH8CRW3JSFY5LAGE
```

Name keys after where they live (`ci`, `laptop`, `agent`) so revoking one later is a decision, not a guess.

> **For AI agents:** Run 
> 
> `typeship login --no-browser`
> 
> : it prints an approval link (also as a JSON event on stderr), you hand the link to the user, they approve once in the console, and the typeship CLI stores the key it is given, named after the machine. No key crosses the conversation. Alternatively the user creates one at 
> 
> [/console/keys](https://typeship.dev/console/keys)
> 
>  and exports it as 
> 
> `TYPESHIP_TOKEN`
> 
> . Until then, 
> 
> `POST /v1/generate`
> 
>  and 
> 
> `typeship generate run`
> 
>  work without a key.

## Send it

Every authenticated request carries the key as a bearer token:

```bash
curl https://typeship.dev/api/v1/me \
  -H "Authorization: Bearer ak_..."
```

A missing or invalid key returns `401` with the code `unauthorized`. A browser session is not a credential for this API. Only keys work.

## OAuth access tokens

An OAuth access token from a sign-in through typeship's MCP server (`/mcp-oauth`, or any OAuth client registered with typeship's authorization server) is accepted wherever a key is: `Authorization: Bearer <access_token>`. It acts as the user who consented, in the first organization they belong to; `X-Typeship-Org: org_...` picks another they are a member of. Tokens expire on the authorization server's schedule and clients refresh them; revoking the client's grant ends access.

## Without a key

`POST /v1/generate` is the one operation that works anonymously. Leave the `Authorization` header off and it behaves like the [generator on the homepage](https://typeship.dev/): the first 25 operations of the spec, rate limited per IP address, nothing stored. The response carries a `limits` object naming what was held back and where to sign up, and, for a spec given by URL, a `claim.url`: a link that, once a person signs in, turns that run into a project in their organization with the same spec, language, platforms, and config (seven days). That is the front door for a script or an agent that has a spec and no account yet. A key that is present but invalid is a `401`, never a silent downgrade to anonymous. Everything else needs a key.

## Rotate and revoke

List keys with `GET /v1/api_keys` and revoke one with `DELETE /v1/api_keys/{id}` (`typeship api-keys list`, `typeship api-keys revoke <id> --force`), or use **revoke** in the console. Revocation takes effect within thirty seconds. Revoked keys stay listed with `revoked: true` for the audit trail. Rotating means creating a new key in the console, moving it into place, and revoking the old one.

Each key records when it was last used, so a key that has gone quiet is easy to spot before you revoke it.

## Scope

Keys have the full permissions of the account, no expiry, and no scopes. Treat them like passwords: environment variables and secret stores, never source control. The one thing a key cannot do is create another key.

## In the tooling

|                     | Where the key goes                                          |
| ------------------- | ----------------------------------------------------------- |
| typeship SDK        | `new TypeshipClient({ bearerToken })`                       |
| typeship CLI        | `TYPESHIP_TOKEN`, `--token`, or `typeship login`            |
| typeship MCP server | `TYPESHIP_TOKEN`, or the credentials `typeship login` saved |
| curl                | `Authorization: Bearer ak_...`                              |

## Sitemap

[Every page of these docs](https://typeship.dev/llms.txt)
