# API keys

The credential resource: how keys are minted and presented.


An **API key** is the credential a team authenticates with. A key belongs to
exactly one team and only ever sees that team's resources.

## Fields

| Field          | Type   | Notes                                                          |
|----------------|--------|----------------------------------------------------------------|
| `id`           | string | `key_`-prefixed. The public part of the credential.            |
| `secret`       | string | The full `key_id:secret` credential. Returned **once**, at mint time. |
| `name`         | string | A label for the key.                                           |
| `last_used_at` | string | ISO 8601 timestamp of the key's last authenticated request, or `null`. |
| `revoked_at`   | string | ISO 8601 timestamp when the key was revoked, or `null` while active. |
| `inserted_at`  | string | ISO 8601 timestamp when the key was minted.                    |

The platform stores only a hash of the secret. After the response that mints a
key, the `secret` is unrecoverable: if it's lost, the key must be replaced.

## How keys are minted

Keys are not created through a standalone endpoint. Your root team's key is
provisioned by TAGBASE when you're onboarded. See
[Obtaining a key](/docs/api/authentication). Every key after that is minted
automatically when you [create a subteam](/docs/api/teams), and returned as an
`included` `api_keys` resource on that response:

```json
{
  "type": "api_keys",
  "id": "key_VfUttEQbh1ceW7jtwV66rF",
  "attributes": { "secret": "key_VfUttEQbh1ceW7jtwV66rF:superstrongrandomsecret" }
}
```

## Presenting a key

Send the full `secret` string as a bearer token on every request. See
[Authentication](/docs/api/authentication) for details and error shapes.

```
Authorization: Bearer key_VfUttEQbh1ceW7jtwV66rF:superstrongrandomsecret
```

## Retrieve an API key

```
GET /api/v1/api_keys/:id
```

Read a key's metadata: its label, when it was last used, and whether it's been
revoked. The key must belong to the team you present, or to a subteam that
team owns; otherwise the platform responds `404`.

The **`secret` is never returned here.** It's shown only once, when the key is
minted (see above); this endpoint exposes only metadata.

<!-- tabs -->
```bash cURL
curl https://platform.tagbase.io/api/v1/api_keys/key_VfUttEQbh1ceW7jtwV66rF \
  -H "Authorization: Bearer $TAGBASE_API_KEY" \
  -H "Accept: application/vnd.api+json"
```
```js
const res = await fetch(
  "https://platform.tagbase.io/api/v1/api_keys/key_VfUttEQbh1ceW7jtwV66rF",
  {
    headers: {
      "Authorization": `Bearer ${process.env.TAGBASE_API_KEY}`,
      "Accept": "application/vnd.api+json",
    },
  },
);
const key = await res.json();
```
```php
$response = $client->get("https://platform.tagbase.io/api/v1/api_keys/key_VfUttEQbh1ceW7jtwV66rF", [
    "headers" => [
        "Authorization" => "Bearer " . getenv("TAGBASE_API_KEY"),
        "Accept"        => "application/vnd.api+json",
    ],
]);
$key = json_decode((string) $response->getBody(), true);
```
```elixir
key =
  Req.get!("https://platform.tagbase.io/api/v1/api_keys/key_VfUttEQbh1ceW7jtwV66rF",
    headers: [
      {"authorization", "Bearer #{System.fetch_env!("TAGBASE_API_KEY")}"},
      {"accept", "application/vnd.api+json"}
    ]
  ).body
```
<!-- /tabs -->

### Response: `200 OK`

```json
{
  "data": {
    "type": "api_keys",
    "id": "key_VfUttEQbh1ceW7jtwV66rF",
    "attributes": {
      "name": "Zanna Therapeutics",
      "last_used_at": "2026-06-08T12:34:56.123456Z",
      "revoked_at": null,
      "inserted_at": "2026-06-01T09:00:00.000000Z"
    }
  }
}
```

### Errors

| Status | When                                                        |
|--------|-------------------------------------------------------------|
| `401`  | Missing, invalid, or revoked key.                           |
| `404`  | No such key, or it isn't owned by the team you present.  |

## Lifecycle

- A team can hold more than one active key, which is what lets you rotate
  without downtime.
- A revoked key stops working immediately and authenticates as `401`.

> You can read a key's metadata by id (above), but self-service endpoints to
> create, list, or revoke a key on an existing team are not part of the public
> API yet. Today a key is minted with its team; rotation and revocation on an
> existing team are handled by TAGBASE.

