---
title: "Demo Credential"
description: "One unauthenticated HTTP call returns a working, scoped, read-only PgBeam credential against our own dataset, so an agent can run the policy engine before it has an account."
canonical: "https://pgbeam.com/docs/demo-credential"
last-updated: "2026-09-07T16:46:46.000Z"
---

# Demo Credential

> One unauthenticated HTTP call returns a working, scoped, read-only PgBeam credential against our own dataset, so an agent can run the policy engine before it has an account.

URL: https://pgbeam.com/docs/demo-credential

Every other way to try PgBeam needs a person: a signup form, an email, a click. This one does not. `POST /v1/demo/credentials` takes no account, no key, and no body, and returns a working Postgres connection string and a hosted MCP token against a dataset PgBeam owns. The credential is read-only, table-scoped, PII-masked, budgeted, and expires in fifteen minutes.

It is the same enforcement path a paying customer's agent runs through. Nothing about the demo is a simulation: the block you see is the wire protocol refusing a statement, and the masked column is the proxy rewriting a result row.

## Get a credential

The connection string and the MCP token are shown once. If you lose them, ask for another credential.

Before you spend a request, `GET /v1/demo` describes the surface: whether it is up, how much of the ceiling is left, what each tier costs, the dataset schema with the treatment applied to every column, and the walkthrough below. It needs no account either.

## The walkthrough

The response carries a `walkthrough` array. Each entry has the SQL to run and the outcome it must produce, so an agent can drive the demo and check its own results without reading this page. Four statements, in order:

**A permitted read returns rows.**

`demo.customers` is on the credential's table allowlist and none of these columns is masked, so you get rows.

**PII comes back masked.**

`full_name` and `email` are redacted, `phone` is replaced with a SHA-256 digest. Masking is keyed on the source column, not the result column name, so `SELECT email AS x` and `SELECT upper(email)` are masked too.

**A table off the allowlist is blocked.**

The table is really there, with real rows in it. You can see it in `information_schema`. The credential still cannot read a row of it, because the allowlist is enforced in the wire protocol before the statement reaches Postgres.

**A write is refused.**

Error text is written for a language model to read: what was refused, why, and what would have to change.

## The dataset

Three tables in the `demo` schema, holding a fictional company's records. Nothing in it is real and nothing in it is a customer's.

Table

Reachable

What it demonstrates

`demo.customers`

yes

Masking: `full_name` and `email` redacted, `phone` hashed

`demo.orders`

yes

A normal read, and the target of the refused write

`demo.employee_salaries`

no

The allowlist: the table exists and every statement naming it is blocked

Relations are schema-qualified on purpose. A demo credential cannot write `search_path` (PgBeam blocks that for agent credentials as an allowlist-evasion guard), so an unqualified name will not resolve.

The dataset is shared by every concurrent demo and every tier is read-only, so nothing you do changes what the next visitor sees.

## Limits

Tier

TTL

Query budget

Max rows

Price

Free

15 min

100

200

free

Extended

4 h

5,000

10,000

$1

The extended tier is bought over HTTP 402. Ask for it with `{"tier": "extended"}`; if no payment has settled you get a 402 carrying the challenge, and you replay the request with `payment_proof` set. `GET /v1/demo` reports `purchasable` per tier, so a client can tell a tier that needs payment from one that cannot be bought here at all.

Beyond the per-credential budget there are two limits on the endpoint itself:

**Per client, three credentials an hour.** Exceeding it returns 429. Releasing a credential does not refund the quota.

**A global ceiling on concurrent live credentials.** When it is full you get 503 with a `Retry-After` naming the seconds until the oldest session expires. It is not a 429, because backing off individually does not create capacity, and it is not a 402, because paying would not either.

If you finish early, hand the slot back so the next agent is not turned away:

## Using the MCP endpoint instead

The same credential comes with a hosted MCP URL and a bearer token, so an MCP client can run the walkthrough as tool calls rather than SQL:

MCP tools run over a loopback Postgres session as the same credential, so they hit the same policy. A `query` tool call against `demo.employee_salaries` is blocked with the same reason the wire path gives. See MCP.

## Taking it to your own database

The response's `policy_template` is the exact policy the demo enforced, in the shape the policy endpoint accepts. That is the upgrade path: nothing about the demo credential carries over (it expires, and it only ever pointed at our dataset), but the policy document does.

See Policies, Allowlists, Masking, and Budgets for what each field does.

## What the demo is not

It is not a sandbox you can write to. For write isolation against your own data, see Sandbox writes, which routes writes to an ephemeral branch.

It is not a free tier of the product. It is a fixed dataset PgBeam owns, sized to demonstrate enforcement, not to build against.

It is not a place to put anything of yours. There is nothing to upload, and the credential cannot create a table.