Okapi

SDK setup

Okapi speaks the Sentry ingest wire format. Most Sentry SDKs work by changing only the DSN — no okapi-specific SDK, no extra configuration.

The DSN model

Okapi authenticates ingest by the DSN public key only — there is no secret component. The DSN format is:

http://<PUBLIC_KEY>@<host>/<project>
  • <PUBLIC_KEY> — from the project's DSN Keys tab in the dashboard.
  • <host> — where Okapi is reachable, e.g. localhost:8480 locally or your production domain.
  • <project> — a trailing path segment. Okapi identifies the project by the key alone and ignores this value, but some SDKs (e.g. sentry-python) validate it as an integer, so use a number like 1. The DSN Keys tab shows a ready-to-copy DSN already in this form.

For production, use https:// and your domain, fronted by a TLS-terminating reverse proxy.

Ingest endpoints

Okapi exposes both Sentry ingest endpoints:

  • POST /api/{project_id}/store/ — the legacy single-event endpoint.
  • POST /api/{project_id}/envelope/ — the modern envelope endpoint, with gzip decompression and CORS support for browser SDKs.

Your SDK picks the right one automatically based on its version — you never call these directly.

Per-platform setup

JavaScript (browser)

import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "http://YOUR_PUBLIC_KEY@localhost:8480/1",
});

Node.js

const Sentry = require("@sentry/node");

Sentry.init({
  dsn: "http://YOUR_PUBLIC_KEY@localhost:8480/1",
});

PHP

\Sentry\init(['dsn' => 'http://YOUR_PUBLIC_KEY@localhost:8480/1']);

Laravel apps typically use sentry-laravel, which reads the same DSN from SENTRY_LARAVEL_DSN or SENTRY_DSN in .env — point that at your Okapi DSN.

Python

import sentry_sdk
sentry_sdk.init(dsn="http://YOUR_PUBLIC_KEY@localhost:8480/1")

Go

import "github.com/getsentry/sentry-go"

func main() {
    err := sentry.Init(sentry.ClientOptions{
        Dsn: "http://YOUR_PUBLIC_KEY@localhost:8480/1",
    })
    if err != nil {
        log.Fatalf("sentry.Init: %s", err)
    }
    defer sentry.Flush(2 * time.Second)
}

Ruby

Sentry.init do |config|
  config.dsn = "http://YOUR_PUBLIC_KEY@localhost:8480/1"
end

Structured logs, over the same DSN

Okapi collects structured logs over the same DSN as errors — no separate shipper. Enable your SDK's logging integration and logs flow in automatically. For example, in Laravel: set the Okapi DSN, SENTRY_ENABLE_LOGS=true, add a sentry_logs channel to LOG_STACK, then use the Log facade as usual. See Issues & logs for how logs are viewed and searched.

Source map uploads

Okapi symbolicates minified browser JavaScript/TypeScript stack traces from source maps you upload at deploy time, matched by Debug ID. It speaks Sentry's upload protocol, so the stock sentry-cli and bundler plugins work unchanged.

1. Create an upload token. Project → Settings → Source maps → New token. Copy it once (only a hash is stored) — tokens are scoped to one project.

2. Inject Debug IDs and upload with sentry-cli:

export SENTRY_URL=https://okapi.example.com        # your Okapi base URL
export SENTRY_AUTH_TOKEN=okapi_xxxxxxxx…           # the upload token
export SENTRY_ORG=okapi                            # ignored by Okapi; any value
export SENTRY_PROJECT=your-project-slug

sentry-cli sourcemaps inject ./dist                # stamp Debug IDs into bundle + maps
sentry-cli sourcemaps upload ./dist                # upload to Okapi

--org is accepted but ignored — the token already scopes the upload to its project.

3. Or use a bundler plugin. The official @sentry/webpack-plugin, @sentry/vite-plugin, etc. work too — set their url to your Okapi base URL, authToken to the upload token, and org/project accordingly. They inject Debug IDs and upload during the build.

Upload before events arrive. Okapi symbolicates before grouping, so an issue's fingerprint is based on the original (stable) frames. Upload maps at deploy time, before the new build starts sending events — events that arrive before their map is uploaded group on the minified frames and won't be re-grouped later.

Storage and retention. Maps are stored in Postgres (gzip-compressed), keyed by Debug ID, and listed under Settings → Source maps where you can delete them. Upload staging chunks are transient and garbage-collected hourly. Source maps are pruned automatically once they haven't symbolicated any event within the event-retention window (OKAPI_EVENT_RETENTION_DAYS); maps still in active use are kept.

Scope. Browser JS/TS (and compile-to-JS) via Debug IDs is the supported path today. Mobile/native symbolication (dSYM, ProGuard/R8, PDB, minidumps) and the legacy release+URL matching are not supported.

Next: Issues & logs.