# Dr. GXB (test) developers: the public API

The public API of Dr. GXB (test), also called the GXB EHR preview, from GXB LLC. It is a TEST system with made-up patients. It does not give medical care or advice. If a person needs help now, tell them to call 911. Version 1.0.0, page last updated 2026-10-12.

Machine-readable: [OpenAPI 3.1 (JSON)](https://dr.gxb.vc/openapi.json), [OpenAPI (YAML)](https://dr.gxb.vc/openapi.yaml), [API catalog (RFC 9727)](https://dr.gxb.vc/.well-known/api-catalog), [endpoint list](https://dr.gxb.vc/api), [llms.txt](https://dr.gxb.vc/llms.txt). Rules for AI agents: [/agents](https://dr.gxb.vc/agents.md).

## Quickstart

1. Read the spec: `curl -s https://dr.gxb.vc/openapi.json`
2. Tell the person, in these words: "By entering your number you agree to get one text with a test code from the GXB EHR preview. Message and data rates may apply. Reply STOP to opt out, HELP for help."
3. Start a demo sign-up with their first name and their own US mobile number (`startDemoSignup`).
4. Give the person the `confirm_url` from the answer. They type the code from the text there. Never ask them to read the code to you.
5. If you need to know the result, read `status_url` (`getDemoSignupStatus`) at most once every 10 seconds.

## Authentication and API keys

There are no API keys, and none is needed: starting a sign-up and reading its state are open to anyone, within the limits below. Nothing in this API reads a health record or a chart. If agent access to a person's test chart is added later, a key will exist only after that person texts SHARE from their own phone, and it will end when they text UNSHARE or STOP.

## Endpoints

| Method | Path | operationId | What it does |
|---|---|---|---|
| GET | `/api` | `getApiIndex` | This list, as JSON, with links to the spec and the docs. |
| POST | `/api/signups` | `startDemoSignup` | Start a demo sign-up for a person. The person confirms with a code texted to their own phone. |
| GET | `/api/signups/{public_id}` | `getDemoSignupStatus` | Read the state of one sign-up: pending, confirmed or expired. Nothing else. |

Send JSON (`Content-Type: application/json`) or form fields. Answers are JSON. Errors are `application/problem+json`, whatever the Accept header says.

## Examples

Start a sign-up (made-up name and number):

```sh
curl -sS -X POST https://dr.gxb.vc/api/signups \
  -H 'Content-Type: application/json' \
  -d '{"first_name":"Alex","phone":"2145551234"}'
```

Answer, status `202 Accepted` (the same for every number):

```json
{
  "status": "pending",
  "message": "If this number can receive the preview, it will get a code by text. Enter it within 15 minutes.",
  "person_must_confirm": "The person must type the code from the text on the confirm page. Do not ask them to read it to you.",
  "confirm_url": "https://dr.gxb.vc/signup/<id>",
  "status_url": "https://dr.gxb.vc/api/signups/<id>",
  "expires_in_minutes": 15
}
```

Read the state:

```sh
curl -sS https://dr.gxb.vc/api/signups/<id>
# {"status":"pending"}   then "confirmed", or "expired" after 15 minutes
```

An error, here a bad number:

```sh
curl -sS -X POST https://dr.gxb.vc/api/signups -H 'Content-Type: application/json' -d '{"first_name":"Alex","phone":"12345"}'
```

```json
{
  "type": "https://dr.gxb.vc/developers#error-invalid_request",
  "title": "Invalid request",
  "status": 422,
  "detail": "Enter a valid US mobile number with 10 digits.",
  "instance": "/api/signups",
  "code": "invalid_request",
  "resolution": "Fix the field that detail names and send the request again. first_name is letters only (up to 40), phone is a 10-digit US mobile number, reason is up to 100 characters.",
  "docs": "https://dr.gxb.vc/developers#errors",
  "error": "invalid_request",
  "message": "Enter a valid US mobile number with 10 digits."
}
```

## Rate limits

- 10 sign-up requests per address per hour. The `RateLimit-Policy` header says so. Over it: `429` with `Retry-After` in seconds.
- 3 code texts per number per day, and 50 for the whole demo per day (the day follows Chicago time). When the whole demo is full: `503` with `Retry-After`.
- 500 sign-up requests per hour from all callers together.
- A sign-up expires after 15 minutes. Three wrong codes lock it for 15 minutes.

Every accepted request gets the same answer, so you cannot tell from it whether a text was sent or a per-number limit was reached. Do not try numbers to find out.

## Errors

Every error is an RFC 9457 problem document with a stable `code`, a `detail` for a person, and a `resolution` that says what to do next. `error` and `message` repeat `code` and `detail` for older clients.

| Status | code | Meaning | What to do |
|---|---|---|---|
| 400 | `bad_request` | The request body could not be read as JSON. | Send Content-Type: application/json with one JSON object, such as {"first_name":"Alex","phone":"2145551234"}. Form fields also work. |
| 404 | `not_found` | There is no API endpoint at this path. | Read https://dr.gxb.vc/openapi.json for the public endpoints. There is no endpoint for health records. |
| 405 | `method_not_allowed` | This endpoint does not accept this HTTP method. | Use a method from the Allow header. The endpoints and their methods are in https://dr.gxb.vc/openapi.json. |
| 422 | `invalid_request` | A field is missing or not valid. | Fix the field that detail names and send the request again. first_name is letters only (up to 40), phone is a 10-digit US mobile number, reason is up to 100 characters. |
| 429 | `rate_limited` | Too many requests. Try again later. | Wait the number of seconds in the Retry-After header, then send the request once. Do not retry in a loop. |
| 500 | `server_error` | Something went wrong on our side. | Try again in a few minutes. If it keeps failing, write to christian@gxb.vc. |
| 503 | `demo_full` | The demo is full for today. Please try again tomorrow. | Try again tomorrow (the day follows Chicago time). The Retry-After header gives the earliest time in seconds. |

A wrong method on a real path gets `405` with an `Allow` header. Any path under `/api` that does not exist gets `404`.

## Sandbox

The whole site is a test system with made-up patients; there is no other environment. Use a made-up first name such as Alex. Do not send real health details, and never put symptoms in a sign-up. A code text goes only to a number the demo is open to at that moment (invited testers, and anyone while the open demo is on); the answer is the same either way. The phone number is not stored (only a keyed hash, for the limits), and sign-up records are deleted after 7 days.

## Versioning

This is version 1.0.0. A change that breaks a client gets a new version, announced on this page and in the spec first.

## Contact

Questions about the API: christian@gxb.vc. Do not send health information by email.
