Skip to content

API reference

Call every Pug endpoint with plain JSON over HTTP POST. Base URLs, request format, auth modes and the Connect error model.

Updated View as Markdown

You can call every endpoint with plain JSON over HTTP POST — two headers (Content-Type: application/json and Connect-Protocol-Version: 1) plus a JSON-encoded body. No client library or codegen is required; see HTTP transport for a curl-ready recipe.

Under the hood the API is built on Connect RPC — a single set of handlers that speaks the Connect, gRPC, and gRPC-Web protocols over the same HTTP endpoints, on both HTTP/1.1 and HTTP/2. Generated clients are available for any language with Buf support, but the plain-JSON path above is all you need.

Base URL

Environment Base URL
Production https://api.pugs.dev
Self-hosted / local http://localhost:3000

The server port for self-hosted deployments defaults to 3000 (configurable via PUG_SERVER_PORT).

Request format

Every Connect RPC endpoint is reachable at:

POST /{package}.{Service}/{Method}

For example:

POST /sdk.events.v1.EventsService/BatchCreate
POST /sdk.profiles.v1.ProfilesSDKService/Identify
POST /shared.insights.v1.InsightsService/Query

For Connect JSON (no generated client needed), send these headers on every request:

Content-Type: application/json
Connect-Protocol-Version: 1

Add the appropriate auth header (see below) and POST a JSON-encoded request body.

Authentication

Auth is enforced at the HTTP middleware layer, before any handler runs. The mode depends on the proto package. For obtaining and rotating keys, see Authentication.

SDK key (sdk.* services)

Send your API key in the x-api-key header:

x-api-key: pub_…   # or prv_…

Two key types are accepted:

Key prefix Access
pub_… Write / ingest only. Safe to embed in browser code via the Web SDK.
prv_… Full read-write. Server-side and trusted environments only.

No Authorization header or x-project-id is required for SDK auth — the project is resolved directly from the key.

Beacon requests (which cannot set headers) may pass a public key as the api_key query parameter. Private keys are rejected on the query parameter path.

JWT (dashboard.* services)

Authorization: Bearer <jwt>

Optionally add x-project-id: <project-id> to scope the request to a specific project (the server verifies org membership). JWT auth is issued by public.auth.v1.AuthService.

Dual — private key or JWT (shared.* services)

Shared services are accessible from both server-side integrations and the dashboard. The server checks x-api-key first; if absent, it falls back to Authorization: Bearer. Only private keys (prv_…) are accepted via this path — public keys are rejected.

x-api-key: prv_…          # server-side path
# — or —
Authorization: Bearer <jwt>   # dashboard path

Public (no auth)

Two services require no credential:

  • public.auth.v1.AuthService — sign-in, magic link, OAuth.
  • public.dashboards.v1.SharedDashboardsService — reads a publicly-shared dashboard. Authorization comes from the unguessable share token carried in the request, so treat that token as a bearer credential: anyone holding it can read the dashboard.

Auth matrix

Proto package Auth mode Header
sdk.* SDK key x-api-key: pub_… | prv_…
dashboard.* JWT Authorization: Bearer <jwt>
shared.* Dual (private key or JWT) x-api-key: prv_… or Authorization: Bearer <jwt>
public.* None — (share token in the request body, where applicable)

Error model

All errors follow the Connect error envelope. For Connect JSON the response body is:

{
  "code": "invalid_argument",
  "message": "events[0].name: value is required"
}

Standard codes returned by the API (HTTP status is the Connect-protocol mapping):

Code HTTP status Meaning
unauthenticated 401 Missing, malformed, or expired credential
permission_denied 403 Valid credential, insufficient access for this operation
invalid_argument 400 Request failed protovalidate — fix the named field and retry
not_found 404 Resource does not exist or is not visible to the caller
already_exists 409 Attempted to create a resource that already exists
failed_precondition 412 Operation rejected due to current system state
resource_exhausted 429 Rate limit exceeded — back off and retry
internal 500 Server-side error — retry with exponential backoff

Connect errors also carry google.rpc.ErrorInfo details (reason + domain) and a google.rpc.RequestInfo with the correlation id, useful for support requests.

Services at a glance

Service Proto name Auth Docs
Events (ingest) sdk.events.v1.EventsService SDK key Events
Profiles (SDK) sdk.profiles.v1.ProfilesSDKService SDK key Profiles
Profiles (read/manage) shared.profiles.v1.ProfilesService Dual Profiles
Insights shared.insights.v1.InsightsService Dual Insights
Activity shared.activity.v1.ActivityService Dual
Orgs dashboard.orgs.v1.OrgsService JWT
Projects dashboard.projects.v1.ProjectsService JWT
Dashboards dashboard.dashboards.v1.DashboardsService JWT
Customers dashboard.customers.v1.CustomersService JWT
Auth public.auth.v1.AuthService None
Shared dashboards public.dashboards.v1.SharedDashboardsService None (share token)

Services showing in the Docs column are dashboard or internal services not covered in this reference. sdk.devices.v1.DevicesService handles push-notification device registration and is likewise out of scope.

For the complete method index see RPC services.

Next steps

  • Events — ingest events with sdk.events.v1.EventsService/BatchCreate
  • Profiles — identify users and read/manage profiles
  • Insights — run analytics queries programmatically
  • HTTP transport — curl-ready plain-JSON recipes
  • RPC services — full package and method map
Navigation

Type to search…

↑↓ navigate↵ selectEsc close