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

# Agent Registration

> Let an AI agent register with DevTune through auth.md, draft a project setup, and act on the project once a person claims it.

An agent can register with DevTune without an account, following [auth.md](https://devtune.ai/auth.md). Before a person claims the registration, the agent can only draft a project setup. After the claim it acts as a project API key, with the scopes that account's plan allows.

## Discovery

| Document | URL |
| - | - |
| Skill | `https://devtune.ai/auth.md` |
| Issuer | `https://devtune.ai/agent` |
| Protected resource metadata | `https://devtune.ai/.well-known/oauth-protected-resource/api/v2/agent` |
| Authorization server metadata | `https://devtune.ai/.well-known/oauth-authorization-server/agent` |
| Signing keys | `https://devtune.ai/agent/jwks.json` |

DevTune accepts the `anonymous` and `service_auth` identity types. The MCP server and the REST API keep their own discovery documents for MCP sign-in and `devtune login`.

## Register

```http theme={null}
POST https://devtune.ai/agent/identity
Content-Type: application/json

{ "type": "anonymous" }
```

Returns `registration_id`, an `identity_assertion` for a `setup.draft` token, a `claim_token`, and `claim_token_expires`. An unclaimed registration expires 7 days after it registers, and the next hourly cleanup deletes it with its draft, claim attempts and email.

```http theme={null}
POST https://devtune.ai/agent/identity
Content-Type: application/json

{ "type": "service_auth", "login_hint": "person@example.com" }
```

Returns a `claim_token` and a `claim` block with the code for the person, in the same shape as `claim_attempt` below. No assertion is issued until the claim completes.

Each IP address can register 5 times an hour for each type. `claim_token` is returned once.

## Claim

Start a claim for an anonymous registration, or a new code for either type:

```http theme={null}
POST https://devtune.ai/agent/identity/claim
Content-Type: application/json

{ "claim_token": "clm_...", "email": "person@example.com" }
```

The code for the person is nested under `claim_attempt`:

```json theme={null}
{
  "registration_id": "REGISTRATION_ID",
  "claim_attempt_id": "CLAIM_ATTEMPT_ID",
  "status": "initiated",
  "expires_at": "2026-11-01T12:10:00.000Z",
  "claim_attempt": {
    "user_code": "USER_CODE",
    "expires_in": 600,
    "verification_uri": "https://devtune.ai/...",
    "interval": 5
  }
}
```

Each IP address can start 5 claims an hour. Each call starts a new attempt and the previous code stops working. Once the person has confirmed the claim, a new attempt is refused with `409 claimed_or_in_flight` while DevTune finishes it. Only the signed-in DevTune user with that email can complete the claim, and five wrong codes lock the attempt.

The person opens `verification_uri`, signs in or signs up, and enters `user_code`. See [What the person sees](#what-the-person-sees).

Poll for the result:

```http theme={null}
POST https://devtune.ai/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_...
```

| Response | Meaning |
| - | - |
| `authorization_pending` | Not confirmed yet. Poll again after `interval`. |
| `slow_down` | Polling too fast. Add 5 seconds to your interval. |
| `expired_token` | The code or registration expired. Start another claim. |
| `invalid_grant` | The claim token was already exchanged. |
| `200` | `access_token`, `expires_in`, `scope`, and a new `identity_assertion` that lasts a year. |

The claim token can be exchanged once. Pre-claim access tokens stop working when the claim completes.

## Access tokens

Exchange an assertion for an access token whenever the last one expires (after an hour):

```http theme={null}
POST https://devtune.ai/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>
```

There are no refresh tokens. `invalid_grant` means the registration expired, the assertion was replaced by the claim or reached its one-year expiry, or the API key was revoked; register again.

Revoke one access token with `POST https://devtune.ai/oauth2/revoke` and `token=<access_token>`. It always returns `200`.

## Scopes

| Scope | When | Allows |
| - | - | - |
| `setup.draft` | Before the claim | Read and replace the registration's setup draft, and read the Agent Picks and AI platform catalogues. Every other route and MCP tool refuses it. |
| API key scopes | After the claim | Everything an API key on the project can do, with every scope the account's plan offers. See [Authentication](https://docs.devtune.ai/api-reference/authentication.md). |

## The setup draft

`GET` and `PUT https://devtune.ai/api/v2/agent/setup-draft` read and replace the draft whole. Over MCP, the same token sees `devtune_get_setup_draft`, `devtune_save_setup_draft`, `devtune_get_public_agent_picks_catalogue` and `devtune_get_public_search_platform_catalogue`.

| Field | Required for | Contents |
| - | - | - |
| `product` | always | `ai-search`, `agent-picks` or `both` |
| `trial_plan` | optional, Agent Picks | `plus`, `pro` or a price id; a new team's `agent-picks` trial starts on it |
| `visibility` | `ai-search`, `both` | `domain`, `brand_context`, `competitors` (`name`, `urls`), `prompts` |
| `agent_picks` | `agent-picks`, `both` | `starting_point` `use_category` with `setup`, or `start_from_scratch` with `job` |

`setup` and `job` take the bodies `PUT /projects/{projectId}/agent-picks/setup` and `PUT /projects/{projectId}/agent-picks/job` accept, with ids from `GET /api/v2/agent/catalogue/agent-picks`. Under `both`, `visibility.competitors` is the one competitor list both products share. A draft cannot choose the AI platforms to probe. Plan limits are applied when the person claims it.

## What the person sees

The claim link opens a page in DevTune that asks the person to sign in first, then:

1. **Code.** They enter the 6-digit code. Five wrong codes lock the claim; start another to get a new code.
2. **Team.** They select the team the project goes in. Only teams whose settings they manage are listed. A team is shown as unavailable, with the reason, when agent connections aren't on for it, its plan doesn't include API access, it doesn't have Agent Picks for an Agent Picks draft, or its prompt allowance has no room for 5 more prompts. Projects belong to teams, so a person with no team creates one here and comes back to the claim.
3. **Name and domain.** They confirm the product name and the domain from the draft, or enter them. DevTune always creates a new project; a name another project has gets a numbered address.
4. **Review.** DevTune fills what the draft left empty: it writes the brand context from the domain, and suggests prompts when the draft has fewer than 5. The person edits the brand context, drops competitors, and selects 5 to 10 prompts within the team's prompt allowance. Agents the team's plan doesn't include are dropped from the Agent Picks setup. Under `both`, Agent Picks tests the competitors on the list whose domains match its tools, so a competitor dropped here is dropped from both.
5. **Connect agent.** DevTune creates the project as the new-project setup does. A team that hasn't had a trial starts its no-card trial; a team with a plan keeps it. DevTune runs the first AI Search probe and requests the Agent Picks starter test, then opens the project. Your next poll returns the access token.

If the team needs a plan first, billing opens in a new tab and the person selects **Continue** on the claim page when they're done. The person can also close the page and open the claim link again: once they've entered the code and picked a team, the link reopens their review without the code, even after the code expires, until you start another claim. Once they confirm, DevTune finishes the project in the background and the page shows its progress; reopening the link shows where it got to and lets the person continue a finish that stopped. A second tab that confirms a different setup is refused.

If you replace the draft while the person reviews it, or after they confirm, DevTune creates what they reviewed. If you start another claim, the old link stops working; the project the person started from it is kept, and the new claim finishes it in the same team.

## After the claim

The registration becomes an API key named **Agent registration** on the project, owned by the person who claimed it. The agent's access tokens act as that key: its scopes, the project's paused state and the account's plan all apply. Revoking the key under **API Keys** ends the agent's access at once.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.