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:8480locally 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 like1. 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.