Skip to content
docs

Authentication

The API authenticates with a publisher key. A key is a bearer token that starts with nln_live_. It binds to one site: a key issued for one site can only read or settle for that site, never another, even if you own both.

Minting a key

Create keys under Settings → API & webhooks. You'll see the token once, at creation, so store it somewhere safe (a secret manager, your deploy env). If you lose it, revoke it and mint a new one; there's no way to recover the original.

The API is a paid-plan capability. A key only works while its site is on a plan that includes API access (Studio and above). Downgrade the site and its keys stop working, and every endpoint returns 403 with {"error": "...", "upgrade": true}.

Sending a key

Send it as a bearer token:

Authorization: Bearer nln_live_xxxxxxxxxxxxxxxxxxxx

A missing or unrecognized key gets 401. A key for the wrong site gets 403: asking verify to settle a payment for a resource on a site the key isn't bound to, for example.

curl https://gate.naulon.app/_naulon/tenants/self \
  -H "Authorization: Bearer nln_live_xxxxxxxxxxxxxxxxxxxx"

Scopes

Each key carries scopes that decide which endpoints it can reach. Pick the narrowest set that does the job.

Scope Unlocks
tenant.read GET /_naulon/quote, POST /_naulon/verify, POST /_naulon/observe, GET /_naulon/tenants/self
earnings.read.all GET /_naulon/earnings and its statements, reconciliation, and export variants
audit.read GET /_naulon/audit
member.read GET /_naulon/members (your author/payee roster)
domain.manage The /_naulon/verify-host writes, proving a runtime owns the domain it enforces on

A key without the scope an endpoint requires is treated as unauthorized for that endpoint. Scopes are independent of the plan gate above: a key needs both the scope for the route and a plan that includes API access.

domain.manage is the only write scope, and the permission matrix does not offer it. It comes on the Connect WordPress preset, expires in 30 days, and is dropped from the key the moment the domain verifies. If you are setting up the plugin, mint that preset rather than building a key by hand; the reason it works that way is in In-app enforcement.