Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{ "name": "neon-postgres", "ref": "main" },
{ "name": "neon-postgres-egress-optimizer", "ref": "main" },
{ "name": "neon-postgres-branches", "ref": "main" },
{ "name": "neon", "ref": "main" },
{ "name": "neon", "ref": "5460c18205b8f7a5bb3bafa173b82e5f53d7f605" },
{
"name": "neon-postgres-agent-platforms",
"ref": "main",
Expand Down
46 changes: 38 additions & 8 deletions content/docs/reference/claimable-neon.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ redirectFrom:
- /docs/reference/neon-launchpad
- /docs/reference/instagres
- /docs/reference/claimable-postgres
updatedOn: '2026-08-25T19:29:40.470Z'
updatedOn: '2026-08-26T18:00:00.000Z'
---

If an agent needs a Neon account and the user is not around, it provisions a project now. A human claims it later if they want to keep it. The agent receives credentials scoped to one project, builds with standard Postgres tools, and hands over a claim link. Unclaimed projects expire in 72 hours and are capped at 100 MB storage and 1 GB transfer.
If an agent needs a Neon account and the user is not around, it provisions a project now. A human claims it later if they want to keep it. The agent receives credentials scoped to one project, builds with standard Postgres tools, and hands over a claim link. Unclaimed projects expire in 72 hours (`project.expires_at`) and are capped at 100 MB storage and 1 GB transfer. Claim codes expire in 15 minutes (`expires_in`). Those are two clocks.

Start in the browser at [neon.com/claimable-neon](/claimable-neon), or give an agent [`auth.md`](https://neon.com/auth.md).

Expand Down Expand Up @@ -196,14 +196,16 @@ Only requested and granted services appear under `services`.
| Capability | Available before claim | Environment variable |
| ------------------- | ---------------------- | ----------------------------- |
| Postgres | Yes | `DATABASE_URL` |
| Data API | When requested | `NEON_DATA_API_URL` |
| Managed Better Auth | When requested | `NEON_AUTH_BASE_URL` |
| Data API | When requested, or later with `neon deploy` | `NEON_DATA_API_URL` |
| Managed Better Auth | When requested, or later with `neon deploy` | `NEON_AUTH_BASE_URL` |
| Functions | No | Requires claiming the project |
| Object Storage | No | Requires claiming the project |
| AI Gateway | No | Requires claiming the project |

Registration records those as `{ granted: false, reason: "requires_claim" }`. A later protected operation returns `capability_requires_claim`. Preserve the denied capability and give the human a claim link; do not retry or drop it.

After create, add Auth or the Data API with `neon.ts` and `neon deploy` on the unclaimed project. After claim, the same config talks to Neon directly.

## Use the Neon CLI

`neon claim` and its `neon claimable` alias manage anonymous projects. If `neon claim` is not a command, or `neon claim --help` does not list `create`, use the HTTP flow in this page.
Expand Down Expand Up @@ -259,13 +261,17 @@ curl --request POST \
}
```

Open `verification_uri_complete` and sign in to Neon. Opening the URL does not freeze access. Continuing to Neon starts the transfer: it revokes the project key, access tokens, and database password before the console transfer URL is shown. Auth and the Data API stay enabled and transfer with the project. Choose the destination organization. The project then moves through these states:
`expires_in` is 900 seconds (15 minutes) today. If the unused code expires, POST `/claim` again. Each POST cancels the previous unused code and returns a new one. Re-issue only while `project.expires_at` is still in the future.

Open `verification_uri_complete` and sign in to Neon. Opening the URL does not freeze access. Continuing to Neon starts a transfer with a new 15-minute window: it revokes the project key, access tokens, and database password before the console transfer URL is shown. Auth and the Data API stay enabled and transfer with the project if they were enabled. If that transfer window expires before you accept, POST `/claim` again. The project key and database password stay revoked.

Choose the destination organization. The project then moves through these states:

1. `pending`: the claim code exists, but the transfer has not completed.
2. `accepted`: the project has left the unclaimed-project organization.
3. `reconciled`: the identity assertion is revoked and the ceremony is finished.

Continuing to Neon revokes existing access tokens. Re-exchange the identity assertion, then poll claim status at the server-provided `interval`. The new token is only good for that poll until `reconciled`.
Continuing to Neon revokes existing access tokens. Re-exchange the identity assertion, then poll claim status at the server-provided `interval`. The new token has no project scopes. It authorizes that poll, and a replacement claim code if the transfer window expires.

```bash
curl --request POST https://claimable.neon.tech/v1/oauth2/token \
Expand All @@ -278,7 +284,31 @@ curl https://claimable.neon.tech/v1/projects/quiet-fog-12345678/claim \
--header "Authorization: Bearer $ACCESS_TOKEN"
```

Only `reconciled` means the assertion is dead. Use credentials from the destination Neon organization after that. Fetch a new `DATABASE_URL` there; Auth and the Data API keep working.
Only `reconciled` means the assertion is dead. Use credentials from the destination Neon organization after that. Fetch a new `DATABASE_URL` there; Auth and the Data API keep working if they were enabled.

Add Auth or the Data API with `neon.ts` and `neon deploy` before or after claim. Data API with the default auth provider requires Auth. An external JWKS is only accepted after claim:

```typescript filename="neon.ts"
import { defineConfig } from '@neon/config/v1';

export default defineConfig({
auth: true,
dataApi: true,
});
```

```bash
neon deploy
```

`neon checkout` does not apply this to an existing branch. `neon deploy` (alias of `neon config apply`) does.

```typescript
dataApi: {
authProvider: 'external',
jwksUrl: 'https://example.com/.well-known/jwks.json',
}
```

## Errors

Expand Down Expand Up @@ -308,7 +338,7 @@ Common codes include:
| `token_expired` | The access token expired. Re-exchange the identity assertion |
| `scope_insufficient` | The access token does not permit the operation |
| `capability_requires_claim` | The requested service or operation requires human ownership |
| `claim_in_progress` | Only claim-status polling remains available |
| `claim_in_progress` | The transfer window is still live. Poll status; mint a new code after it expires |
| `project_claimed` | The project transferred. Discard the identity assertion |
| `project_expired` | The unclaimed window closed. Discard the identity assertion |
| `upstream_error` | A Neon API or service dependency failed |
Expand Down
2 changes: 1 addition & 1 deletion public/.well-known/agent-skills/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"type": "skill-md",
"description": "Overview of Neon, a complete set of cloud backend primitives for apps and agents, spanning Lakebase Postgres, Auth, the Data API, Object Storage, Compute Functions, and the AI Gateway. Start here to route to the right Neon skill, set up the CLI or MCP server, and follow the branch-first workflow. Use when \"Neon\" or \"Lakebase Postgres\" is mentioned, or when any of its individual capabilities are the trigger: \"object storage\" or \"S3\", \"buckets\", \"serverless functions\", \"AI gateway\", \"call an LLM\", \"logs\", \"branch logs\", \"query logs\", \"log export\", \"Loki\", \"Grafana\", \"observability\", \"telemetry\", \"postgres\", \"database\", or \"backend\". Also use when there is no Neon account yet, the user cannot sign in or provide an API key right now and needs a project they can claim later, or the user asks for a throwaway DATABASE_URL, Claimable Neon, Claimable Postgres, neon.new, claimable.neon.tech, instant Postgres, a no-signup database, temporary postgres, quick postgres, a no credit card database, or npx neon-new.",
"url": "/.well-known/agent-skills/neon/SKILL.md",
"digest": "sha256:9e3aafe76e94c6dba997e164ff0a9d51431f79b04ecd36d78ae41d7ef1333bfe"
"digest": "sha256:29517ac4c13fed5574d9cc99ccf2dd9c7d78b2e966c220b400eeeb4f0f5b2128"
},
{
"name": "neon-postgres-agent-platforms",
Expand Down
47 changes: 42 additions & 5 deletions public/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,21 @@ POST https://claimable.neon.tech/v1/projects/<project_id>/claim
Authorization: Bearer <access_token>
```

The unclaimed project expires at `project.expires_at` (72 hours today). A claim code expires in
`expires_in` seconds (900 today). If the unused code expires, POST this endpoint again. Each POST
cancels the previous unused code and returns a new one. Re-issue only while `project.expires_at`
is still in the future.

Open the returned `verification_uri_complete`. Opening the URL does not freeze access. Continuing
to Neon starts the transfer and rotates `DATABASE_URL`. The human signs in to Neon, selects a
destination organization, and accepts the transfer.
to Neon starts a transfer with a new `expires_in` window, revokes access tokens, and rotates
`DATABASE_URL`. If that window expires before the human accepts, POST this endpoint again. The
project key and database password stay revoked.

The human signs in to Neon, selects a destination organization, and accepts the transfer.

Continuing to Neon revokes existing access tokens. Re-exchange the identity assertion; while the
claim is in progress, the new token has no project scopes and authorizes only claim-status polling:
claim is in progress, the new token has no project scopes and authorizes claim-status polling and
a replacement claim code if the transfer window expires:

```http
POST https://claimable.neon.tech/v1/oauth2/token
Expand All @@ -146,8 +155,36 @@ Authorization: Bearer <claim_status_access_token>
The claim moves through `pending`, `accepted`, and `reconciled`. Stop using pre-claim
credentials when the browser claim starts. At `reconciled`, the identity assertion, access
tokens, project key, and database password no longer authorize project access. Auth and the
Data API stay enabled and transfer with the project. The status endpoint keeps returning the
terminal `reconciled` state when retried with the retained status token.
Data API stay enabled and transfer with the project if they were enabled. The status endpoint
keeps returning the terminal `reconciled` state when retried with the retained status token.

## Add Auth or the Data API

They stay off unless requested at create or enabled later. On the unclaimed project, `neon.ts`
plus `neon deploy` enables them. After claim, the same config talks to Neon directly. Data API
with the default auth provider requires Auth:

```typescript
import { defineConfig } from "@neon/config/v1";

export default defineConfig({
auth: true,
dataApi: true,
});
```

```bash
neon deploy
```

An external JWKS is not accepted on the unclaimed project. After claim:

```typescript
dataApi: {
authProvider: "external",
jwksUrl: "https://example.com/.well-known/jwks.json",
}
```

## Delete or revoke

Expand Down
2 changes: 1 addition & 1 deletion public/docs/.well-known/agent-skills/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"type": "skill-md",
"description": "Overview of Neon, a complete set of cloud backend primitives for apps and agents, spanning Lakebase Postgres, Auth, the Data API, Object Storage, Compute Functions, and the AI Gateway. Start here to route to the right Neon skill, set up the CLI or MCP server, and follow the branch-first workflow. Use when \"Neon\" or \"Lakebase Postgres\" is mentioned, or when any of its individual capabilities are the trigger: \"object storage\" or \"S3\", \"buckets\", \"serverless functions\", \"AI gateway\", \"call an LLM\", \"logs\", \"branch logs\", \"query logs\", \"log export\", \"Loki\", \"Grafana\", \"observability\", \"telemetry\", \"postgres\", \"database\", or \"backend\". Also use when there is no Neon account yet, the user cannot sign in or provide an API key right now and needs a project they can claim later, or the user asks for a throwaway DATABASE_URL, Claimable Neon, Claimable Postgres, neon.new, claimable.neon.tech, instant Postgres, a no-signup database, temporary postgres, quick postgres, a no credit card database, or npx neon-new.",
"url": "/docs/.well-known/agent-skills/neon/SKILL.md",
"digest": "sha256:9e3aafe76e94c6dba997e164ff0a9d51431f79b04ecd36d78ae41d7ef1333bfe"
"digest": "sha256:29517ac4c13fed5574d9cc99ccf2dd9c7d78b2e966c220b400eeeb4f0f5b2128"
},
{
"name": "neon-postgres-agent-platforms",
Expand Down
2 changes: 1 addition & 1 deletion public/docs/ai/skills/neon/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ If the Getting Started account check found credentials, use them. If a command w

If they cannot sign in or provide a key right now, ask before using Claimable Neon. Continue only after they say yes. That is a temporary workaround.

If there is no Neon account yet, follow [references/claimable-neon.md](https://neon.com/docs/ai/skills/neon/references/claimable-neon.md). Do not run `neon init --agent` or `neon auth` on this path; those need a human Neon account. If `neon claim` is missing, the reference has the REST fallback.
If there is no Neon account yet, follow [references/claimable-neon.md](https://neon.com/docs/ai/skills/neon/references/claimable-neon.md). Do not run `neon init --agent` or `neon auth` on this path; those need a human Neon account. If `neon claim` is missing, the reference has the REST fallback. Unclaimed projects expire at `project_expires_at` (72 hours today). Claim codes expire in `expires_in` (15 minutes today). Add Auth or the Data API with `neon.ts` and `neon deploy` before or after claim.

Requests for neon.new, Claimable Postgres, claimable.neon.tech, instant Postgres, or a no-signup database are the same path.

Expand Down
38 changes: 34 additions & 4 deletions public/docs/ai/skills/neon/references/claimable-neon.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,43 @@ export default defineConfig({

Before claim, Postgres is always granted; Auth and the Data API are granted when requested. Functions, Object Storage, and AI Gateway come back with `granted: false` and `reason: "requires_claim"`. The CLI prints those as `denied_capabilities`. Report what you were given. Do not retry or strip them.

After create, report the `project_id`, `project_expires_at`, and any denied capabilities. Do not invent the window.
After create, report the `project_id`, `project_expires_at`, and any denied capabilities. Do not invent the window. Unclaimed projects expire at `project_expires_at` (72 hours today). That clock is independent of the claim code.

## Claim

Do not mint a claim URL until the human is ready. Opening the URL does not freeze access. Continuing to Neon starts the transfer and rotates `DATABASE_URL`. Existing access tokens are revoked. Auth and the Data API stay enabled when they were granted.

When `reconciled` is true, the pre-claim `DATABASE_URL` no longer works. Auth and Data API URLs stay. The human signs in with `neon auth`. Then the agent runs `neon link --agent` and `neon env pull` to write the new `DATABASE_URL`. `neon link --agent` discovers the project after that sign-in.
A claim code expires in `expires_in` seconds (15 minutes / 900 today). If the unused code expires, mint another: `neon claim accept --no-open` or `POST /v1/projects/{id}/claim`. Each mint cancels the previous unused code. You can mint several times; only the latest unused code works. Re-issue only while `project_expires_at` is still in the future.

Continuing to Neon starts a transfer with a new 15-minute window and leaves the project key and database password revoked. If that window expires before the human accepts, mint again. Do not restore pre-claim `DATABASE_URL`.

When `reconciled` is true, the pre-claim `DATABASE_URL` no longer works. Auth and Data API URLs stay if they were granted. The human signs in with `neon auth`. Then the agent runs `neon link --agent` and `neon env pull` to write the new `DATABASE_URL`. `neon link --agent` discovers the project after that sign-in.

Auth and the Data API stay off unless requested at create or enabled later. On the unclaimed project, `neon.ts` plus `neon deploy` enables them. After claim, the same config talks to Neon directly. An external JWKS is only accepted after claim. Data API with the default auth provider requires Auth:

```typescript
import { defineConfig } from "@neon/config/v1";

export default defineConfig({
auth: true,
dataApi: true,
});
```

```bash
neon deploy
```

```typescript
export default defineConfig({
dataApi: {
authProvider: "external",
jwksUrl: "https://example.com/.well-known/jwks.json",
},
});
```

`neon checkout` does not apply this to an existing branch. `neon deploy` (alias of `neon config apply`) does.

### With the CLI

Expand All @@ -62,9 +92,9 @@ neon claim delete --yes

### With REST

An agent must not complete the claim. Do not `POST /v1/projects/{id}/claim` until the human is ready. The human opens `verification_uri_complete` and accepts the transfer. If the claim code expires, `POST /v1/projects/{id}/claim` again. The live claim response also includes `user_code` and `expires_in`. `auth.md` documents `verification_uri_complete` and the polling `interval`.
An agent must not complete the claim. Do not `POST /v1/projects/{id}/claim` until the human is ready. The human opens `verification_uri_complete` and accepts the transfer. If the claim code expires, `POST /v1/projects/{id}/claim` again. Each POST replaces the unused previous code. If the human continued to Neon and that transfer expired, POST again for a new code. The live claim response also includes `user_code` and `expires_in`. `auth.md` documents `verification_uri_complete` and the polling `interval`.

After the human continues to Neon, existing access tokens are revoked: re-exchange the identity assertion, then poll `GET /v1/projects/{id}/claim` with that token at the interval `auth.md` returns. `claim_in_progress` means keep polling with the post-redemption token, not the token from create. Report `verification_uri_complete`, `user_code`, and `expires_in`.
After the human continues to Neon, existing access tokens are revoked: re-exchange the identity assertion, then poll `GET /v1/projects/{id}/claim` with that token at the interval `auth.md` returns. `claim_in_progress` on a new mint means the transfer window is still live: poll, do not mint. After that window expires, POST claim again. Report `verification_uri_complete`, `user_code`, and `expires_in`.

When `error.code` is `capability_requires_claim`, preserve the denied capability and give the human a claim link instead of retrying or silently omitting it.

Expand Down
Loading