developers  · docs
Get your token
Docs · Authentication

Authentication

Updated Aug 2026 · API v3

Two ways in, one rule: who owns the data decides the mechanism.

Personal access tokens

A PAT acts as you — it can only ever reach your own lists, items and profile. Plain Authorization: Bearer pon_pat_…, nothing else. Use it for scripts, cron jobs, Home Assistant, dashboards.

  • Created at my.pon.app → Access tokens, scoped per token.
  • Expiry: 90 days by default, up to 365, or never-expiring if you choose.
  • Up to 10 tokens per account; the secret is shown exactly once.
  • PATs cover the lists, products and profile scopes — the media scopes are reserved for OAuth apps.

OAuth 2.1 for apps with users

The moment your integration signs in someone else, use OAuth 2.1 Authorization Code + PKCE. Users authenticate on the hosted login at auth.pon.app — your app never sees a password — and the issued tokens are DPoP-bound (RFC 9449), so a stolen token is useless without your key.

  • Discovery is standard OIDC: point your library at the issuer (https://auth.pon.app) and everything configures itself.
  • There is deliberately no client_credentials grant — every piece of pon data belongs to a user, so there is no “app-only” data to grant.

Client registration for OAuth partners is currently manual.

Write to developers@pon.app and we set up your client — self-service registration comes later.

Scopes

Scope Meaning
lists:read Read your lists and items
lists:write Create and change lists and items
products:read Read product suggestions and barcodes
products:write Contribute product data
profile:read Read your profile basics
media:read Read images (OAuth apps only)
media:write Upload images (OAuth apps only)

Request the smallest set that works — you can always create another token with more.

Errors you’ll meet

  • 401 UNAUTHORIZED — missing/expired token, or a DPoP proof problem (the WWW-Authenticate header tells you which).
  • 403 DEVELOPER_MODE_REQUIRED — the account never enabled developer mode.
  • 403 EMAIL_UNVERIFIED — confirm the account’s e-mail address first.