# qURL Credentials and Authentication

> The three qURL credential types — API key, enrollment token, and device credential — what each one proves, which one a job needs, and what scopes mean.

Source: https://layerv.ai/docs/credentials/

---

Concept guide

# Credentials and authentication.

qURL has three credentials. You create two of them, and the platform issues the third. This page explains what each one proves, which one a job needs, and what scopes decide — which is permissions, and only permissions.

[See the three types](https://layerv.ai/docs/credentials/#types) [Which one do I want?](https://layerv.ai/docs/credentials/#choose)

The mint example calls `https://api.layerv.ai/v1`.

[The three types](https://layerv.ai/docs/credentials/#types) [The proof rule](https://layerv.ai/docs/credentials/#proof) [Which one do I want?](https://layerv.ai/docs/credentials/#choose) [Creating credentials](https://layerv.ai/docs/credentials/#create) [Scopes and who may mint](https://layerv.ai/docs/credentials/#scopes)

The model

## One you hold, one you mint, one the platform issues.

Every credential in your account reports its `kind`. That field is the whole model: it tells you what the credential is, how long it lives, and who was allowed to create it. Treat `kind` as an open set — new kinds may appear as the model grows, so switch on the kinds you handle and ignore the rest rather than rejecting the response.

01 

### API key — `kind: api_key`

The durable account credential you manage. It calls the API, and its scopes are permissions — they decide what the key may do, never what the key is. An API key can also enroll an agent interactively: the platform emails a one-time code to your account and the agent returns it. With the qurl:agent scope, the key can mint enrollment tokens.

Lifetime

Durable — no expiry, except a child key minted by another key

Proven by

Proof of account ownership (dashboard sign-in, or an emailed one-time code)

Created by

You, in the dashboard

02 

### Enrollment token — `kind: enrollment_token`

A single-use credential that enrolls exactly one target — an agent or a connector. It is the only headless enrollment path: no mailbox is involved, because the token was minted for one enrollment and is its own proof. It can be limited to one resource claim, so a token minted for the connector my-app can enroll nothing else.

Lifetime

One-shot, 24 hours maximum

Proven by

The token itself

Created by

You, from the dashboard session or an API key holding qurl:agent

03 

### Device credential — `kind: device`

When an agent or connector finishes enrolling, the platform mints this and the machine stores it. From that point on it is that machine’s identity: restarts reuse it, and no enrollment token or emailed code is needed again. It appears in credential listings so you can see and revoke it; it can never be created through the API.

Lifetime

Durable — the machine keeps it

Proven by

Issued by the platform at the end of a successful enrollment

Created by

The platform, never you

The rule behind the model

## Durable and general → the platform emails a code. Short-lived and purpose-built → the credential is its own proof.

An API key is durable and can do many things, so creating one — or enrolling a machine with one — has to prove the account really wants it. That proof is your dashboard sign-in, or a one-time code the platform emails to the account.

An enrollment token is the opposite: it exists for one enrollment, expires within a day, and can be pinned to a single resource. There is nothing left to prove, so no code is emailed and no mailbox has to exist. That is why it is the only credential that works on a machine nobody can read mail on.

Which one do I want?

## Start from the job, not the credential.

### I want to call the API from my backend.

An API key. Create it in the dashboard, give it only the scopes that backend needs, and store it in your secret manager.

### I am starting a service or agent and something can read a mailbox.

An API key plus the emailed code. This is the default path and needs nothing minted in advance — see the Go SDK agent guide.

### I am starting a service or agent and nothing can read a mailbox.

An enrollment token with target=agent. Mint it just before the run and pass it to the runtime; it expires within 24 hours whether it is used or not.

### I am installing a connector next to a private service.

An enrollment token with target=connector, bound to that connector id with a claim. The connector consumes it on first start — see the connector enrollment guide.

### My machine already enrolled and is restarting.

Nothing. It holds a device credential. Do not mint a second enrollment token for a machine that already enrolled.

### I want one credential for a CI job that only reads.

An API key scoped to qurl:read. Scopes are how you narrow an API key; there is no smaller durable credential.

### Then follow the guide for that machine

The credential is only the first step. Both onboarding guides pick up from the credential you just chose.

[Connect an agent with the Go SDK](https://layerv.ai/docs/agents/) [Deploy the Enterprise connector](https://layerv.ai/platform/connector/)

Creating credentials

## API keys come from the dashboard. Enrollment tokens come from one request.

Both customer-created credentials are `POST /v1/api-keys` underneath, and `kind` picks what you get. The plaintext secret is in the create response and in no list or get response, so store it before you close the terminal. Send an `Idempotency-Key` header: for 24 hours, a retry with the same key and body returns the original response, secret included, instead of minting a second credential.

### An API key

Create API keys in the [dashboard](https://layerv.ai/qurl/dashboard/keys/), where your sign-in is the proof of account ownership. Give the key only the scopes its job needs; the option to mint connector enrollment tokens is the `qurl:agent` scope. The plan limit is 3 keys on the free tier and 50 on the growth plan.

### An enrollment token

Call the API with an API key that holds `qurl:agent`. Set `target: connector` and bind the token to the connector id with one claim, and it can enroll that connector and nothing else — safe to hand to whoever runs the install. For an agent, set `target: agent` and leave `claims` out, or add a connector claim to restrict the agent to one connector.

`expires_in` is optional and defaults to 24 hours, which is also the ceiling. Mint the token close to when it will be used. Do not send `scopes`: a token’s scopes are server-assigned from its target.

POST /v1/api-keys

```
# QURL_API_KEY is an account key with qurl:agent.
curl -X POST https://api.layerv.ai/v1/api-keys \
  -H "Authorization: Bearer $QURL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "kind": "enrollment_token",
    "name": "prod-dashboard connector enrollment",
    "target": "connector",
    "claims": [{ "type": "connector", "id": "prod-dashboard" }],
    "expires_in": "2h"
  }'
```

201 Created

```
{
  "data": {
    "key_id": "key_def456abc123",
    "api_key": "lv_live_b7k2...",
    "key_prefix": "lv_live_b7k2",
    "kind": "enrollment_token",
    "target": "connector",
    "claims": [{ "type": "connector", "id": "prod-dashboard" }],
    "name": "prod-dashboard connector enrollment",
    "scopes": ["qurl:agent", "qurl:write"],
    "status": "active",
    "created_at": "2026-08-04T10:30:00Z",
    "expires_at": "2026-08-04T12:30:00Z"
  },
  "meta": { "request_id": "req_def456" }
}
```

### After the token is used

- A successful enrollment consumes the token and the platform mints the machine a device credential. A second enrollment with the same token returns 409 `bootstrap_key_consumed`: mint a fresh one, and never retry the same token concurrently.
- Unused tokens are listed in the dashboard, and every credential on the account, device credentials included, is in `GET /v1/api-keys`. Revoke from either place. Revoking an API key does not revoke the devices enrolled through it or the child keys it created; revoke those separately.

Scopes

## Scopes are permissions. They are not a credential type.

A scope narrows what an API key may do. It never changes what the key is: an API key with `qurl:agent` is an ordinary durable API key that can also mint enrollment tokens. For a credential that is narrow in *time* and pinned to one resource, reach for an enrollment token, not a scope.

### `qurl:read`

Read qURLs, resources, and quota.

### `qurl:write`

Create, update, and revoke qURLs and resources. Also covers webhook management.

### `qurl:resolve`

Redeem access tokens headlessly and share resources by CRID.

### `qurl:agent`

Mint enrollment tokens and manage agent and connector enrollment. An API key without this scope cannot create an enrollment token for either target.

### `qurl:keys`

Manage credentials from an API key: list, get, and revoke them, and create short-lived child keys. Without it, those need a dashboard session.

### Who may mint what

- A dashboard session may create API keys and enrollment tokens. Granting a new key `qurl:agent` or `qurl:keys` requires the session to hold that scope itself.
- An API key holding `qurl:agent` may create enrollment tokens for either target.
- An API key holding `qurl:keys` (with `qurl:write` or `qurl:agent`) may create a child API key on an unlimited plan. A child key’s scopes are a subset of its parent’s, never include `qurl:keys`, and it expires within 24 hours and no later than the parent. Without `qurl:keys`, an API key cannot create, list, or revoke API keys. Editing a key’s name or scopes always needs a dashboard session.
- An enrollment token may not create any credential.
- A device credential may create only a connector enrollment token within its own binding.

Next

## Pick a credential, then enroll something.

The full request and response schemas, including every field, error code and status, live in the API reference under API Keys.

[Open the API reference](https://layerv.ai/docs/) [Connect an agent](https://layerv.ai/docs/agents/) [Deploy the Enterprise connector](https://layerv.ai/platform/connector/)



---

*This markdown version is auto-generated from [https://layerv.ai/docs/credentials/](https://layerv.ai/docs/credentials/) for AI agents. Curated agent resources: [llms.txt](https://layerv.ai/llms.txt). For the full interactive experience, visit the HTML version.*

