Skip to content

Ingest keys

An ingest key is a pair: a public key id that identifies the project, and a secret that proves you hold it. The console shows the secret once, at creation, and stores only a SHA-256 hash of it, compared in constant time on every request. Lose it and you create a new key rather than recovering the old one.

A key belongs to exactly one project. That is what decides where an event is stored, so a key is the only thing a sender needs to be pointed at the right place.

Both are the same credential, spelled for whichever field your config already has.

One token. ClientOptions.Token is sent as Authorization: Bearer <key_id>.<secret>:

package main
import (
"context"
"os"
"github.com/kataras/patrol"
)
func main() {
ctx := context.Background()
client := patrol.NewClient(patrol.ClientOptions{
BaseURL: "https://api.patrol.hellenic.dev",
Token: os.Getenv("PATROL_KEY"), // pk_....sk_...
})
producer := patrol.NewProducer(patrol.ProducerOptions{ProjectName: "checkout-api"}, client)
defer producer.Close(ctx)
}

A username and password. ClientOptions.BasicAuth sends the key id as the username and the secret as the password, over HTTP Basic. This is the form that was there before v0.0.7, and it still works.

Set one, not both: when both are present the client sends the token and never the username and password.

Keys are per project and there can be several, so a rotation is additive and needs no downtime:

  1. Create a second key in the console.
  2. Deploy your services with the new value in PATROL_KEY.
  3. Watch the old key’s “last used” go quiet in the console.
  4. Revoke the old key.

Revoking takes effect within a minute: the server caches key lookups briefly, and a revoked key is a cache miss rather than a cached hit.

The ingest endpoint answers 401 with {"http_error_code":"UNAUTHENTICATED"}, which a patrol.Client surfaces as a patrol.ServerError. Switch on patrol.ErrorCodeUnauthenticated in your OnError to tell a bad credential apart from a network failure. The HTTP client page has that code.

Repeated failures from one address are rate limited, so a sender looping on a wrong key backs off rather than being punished.

The key is a secret. It belongs in the environment or in your secret store, not in the YAML file you commit. The _examples in the library follow the same rule: every one of them reads a *.example.yml you copy and fill in, and the real file is gitignored.

Next: destinations.