# Quick start

Source: https://checkend.com/docs/quick-start (Markdown: https://checkend.com/docs/quick-start.md)

> This guide shows how to run Checkend, connect an app with a Sentry SDK, and read the errors.

You need:

- Node 22.18 or later
- a clone of the [Checkend repository](https://github.com/Checkend/checkend), with `npm ci` done
- for a deploy: a Cloudflare account and `npx wrangler login`

## 1. Run Checkend on your computer

1. Create the local database tables:

   ```sh
   npx wrangler d1 migrations apply DB --local
   ```

2. Make an admin token, and put it in `.dev.vars` (this file is git-ignored):

   ```sh
   echo "ADMIN_TOKEN=$(openssl rand -hex 32)" > .dev.vars
   ```

3. Start the Worker:

   ```sh
   npm run dev
   ```

4. Check that it runs:

   ```sh
   curl http://localhost:8787/health
   ```

   The response has `"status": "ok"`. See [Settings and health](https://checkend.com/docs/settings.md#health) for the
   other fields.

## 2. Or deploy it to your Cloudflare account

To run Checkend without Cloudflare, in Docker, on Node, or on a server over SSH, see
[Run without Cloudflare](https://checkend.com/docs/self-host.md).

The first path is `ce server install cloudflare` (see
[the ce CLI](https://checkend.com/docs/cli.md#install-and-manage-a-server)). It makes the Worker and the D1 database on your
account, with a Cloudflare API token. It installs only a signed
[server release](https://checkend.com/docs/operations.md#server-releases), shows the plan and asks first, and ends with the
setup link of the web UI:

```sh
ce server install cloudflare
```

Or do the steps below by hand.

> **Caution:** a deploy uses resources in your Cloudflare account. On the Workers Free plan, also
> set `D1_DAILY_ROW_LIMIT` (see [Budget mode](https://checkend.com/docs/settings.md#budget-mode-workers-free-plan)).

1. Create a D1 database. Wrangler prints its `database_id`.

   ```sh
   npx wrangler d1 create checkend
   ```

2. Copy `wrangler.jsonc` to `wrangler.<name>.jsonc`, for example `wrangler.mine.jsonc`. In the
   copy, set your Worker `name`, and add the `database_id` to the `DB` entry. Files with the name
   `wrangler.*.jsonc` are git-ignored, so your resource IDs stay out of the repository.

3. Apply the migrations and deploy:

   ```sh
   npx wrangler d1 migrations apply DB --remote --config wrangler.mine.jsonc
   npx wrangler deploy --config wrangler.mine.jsonc
   ```

4. Set the admin token as a Worker secret. Until the secret is set, the API answers `401`.

   ```sh
   npx wrangler secret put ADMIN_TOKEN --config wrangler.mine.jsonc
   ```

For a project with many users, also add a rate limiting rule in front of ingest: see
[Protect the ingest path](https://checkend.com/docs/sending-errors.md#protect-the-ingest-path).

Apply the migrations before each deploy. Wrangler records each applied migration and skips it,
so it is safe to run the command again.

## 3. Create a project and get a DSN

A project is one app. Each project has a DSN: the address that the Sentry SDK sends errors to.

**Figure: Create a project.** Running npm run project -- create --name "My App" --platform node prints: Created project 4821937065 (my-app). DSN: https://8c1f4d0e9b7a42f6a3e5d2c1b0f9e8d7@checkend.example.workers.dev/4821937065. Put the DSN in your Sentry SDK: Sentry.init({ dsn: "..." }).

```sh
export CHECKEND_URL=https://<your-worker>      # or http://localhost:8787
export CHECKEND_ADMIN_TOKEN=<your ADMIN_TOKEN>

npm run project -- create --name "My App" --platform node
```

The command prints the project ID and the DSN. To see all projects and their DSNs later:

```sh
npm run project -- list
```

Add `--json` to either command for JSON output.

**Figure: The parts of a DSN.** A DSN has the form https://<public key>@<your Worker host>/<project ID>, where the project ID is a random 10-digit public ID, for example https://8c1f4d0e9b7a42f6a3e5d2c1b0f9e8d7@checkend.example.workers.dev/4821937065. The public key is 32 hex characters. It identifies the project and only lets a client send events; it does not give read access.

## 4. Connect your app

Use any Sentry SDK. Put the Checkend DSN in `Sentry.init`. For example, in Node:

```js
import * as Sentry from "@sentry/node";

Sentry.init({ dsn: "https://<key>@<your-worker>/<project-id>" });
```

Browser SDKs work too: the ingest endpoints allow requests from other origins (CORS).

Checkend keeps **error events only** (exceptions and `captureMessage`). It drops sessions,
transactions, client reports and attachments. See [Send errors](https://checkend.com/docs/sending-errors.md).

## 5. Read the errors

```sh
curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues"
```

Each issue is a group of events with the same cause. To see one issue and its events:

```sh
curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues/1"
curl -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" "$CHECKEND_URL/v1/issues/1/events"
```

See [API](https://checkend.com/docs/api.md) for all endpoints.

**Figure: Read the issues.** Example response of GET /v1/issues?limit=1 (formatted with jq):

```json
{
  "data": [
    {
      "id": 1,
      "project_id": 4821937065,
      "title": "TypeError: Cannot read properties of undefined (reading 'id')",
      "culprit": "loadUser (src/users.ts)",
      "type": "TypeError",
      "level": "error",
      "platform": "node",
      "status": "unresolved",
      "times_seen": 42,
      "stored_events": 42,
      "events_24h": 42,
      "events_7d": 42,
      "users_affected": 2,
      "priority": 198.462,
      "first_seen": "2026-10-10T14:02:11.087Z",
      "last_seen": "2026-10-10T15:47:03.412Z",
      "first_release": "my-app@1.4.0",
      "last_release": "my-app@1.4.0",
      "fingerprint": "5d41402abc4b2a76b9719d911017c592",
      "fingerprint_version": 1,
      "merged_into": null,
      "claim": null,
      "trust": "high"
    }
  ],
  "next_cursor": "WyIyMDI2LTEwLTEwVDE1OjQ3OjAzLjQxMloiLDFd",
  "ingest": {
    "mode": "full",
    "rows_written_today": 509,
    "daily_row_limit": null,
    "events_received_today": 42,
    "write_failures_today": 0,
    "retry_after_seconds": 0
  }
}
```

## 6. Give your coding agent a read-only token

Do not give the admin token to an agent. Create a token that can only read issues:

```sh
curl -X POST "$CHECKEND_URL/v1/tokens" \
  -H "Authorization: Bearer $CHECKEND_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "claude-code", "scopes": ["issues:read"]}'
```

The response has the token (`ck_...`). Copy it now: Checkend shows it only once. Give it to the
agent as its bearer token. To revoke it later, use `DELETE /v1/tokens/:id`.

If the agent must also resolve, ignore or merge issues, create its token with
`"scopes": ["issues:read", "issues:write"]`.

## 7. Connect your coding agent with MCP

Add the Checkend MCP server to your agent with the read-only token. For Claude Code:

```sh
claude mcp add --transport http checkend "$CHECKEND_URL/mcp" \
  --header "Authorization: Bearer <token>"
```

Then ask the agent, for example: "Fix the top unresolved error in Checkend." The agent calls
`list_issues`, then `get_issue_brief`. See [MCP server](https://checkend.com/docs/mcp.md) for the tools and the issue
brief.

To let Checkend check in production that the fixes work, report your deploys. See
[Verify fixes](https://checkend.com/docs/fix-loop.md).
