Authentication
Entity-scoped API keys, scopes, and the request flow through the Cloudflare edge and Unkey.
Authentication
Wine2You uses entity-scoped API keys. One key belongs to exactly one entity, and the API never trusts a key beyond the entity it is bound to.
The request flow
your system
│ Authorization: Bearer <key>
▼
api.wine2you.shop ← Cloudflare edge; Access service token for machine-to-machine
▼
Wine2You API
├─ Unkey verifies the key → resolves entity_id + scopes + rate/quota bucket
├─ OpenFGA authorises the action (can_read_offers, can_write_listings, …)
└─ read-path filter applies C1–C4 before any row is serialised
▼
scoped result (only rows your entity may see)
Keys
| Property | Value |
|---|---|
| Issuer | Partner portal → POST /api/keys (gated by OpenFGA can_mint_key) |
| Plaintext | shown once at creation; never retrievable again |
| Binding | one key ↔ one entity_id |
| Scopes | e.g. read:offers, write:offers, read:orders, read:network |
| Limits | per-key request rate and per-key record quota (C3) |
Scopes
| Scope | Grants |
|---|---|
read:wines, read:offers, read:listings |
read the corresponding resource within your entity's filter |
write:offers, write:listings |
create/update your own offers and listings |
read:orders |
read orders your entity participates in |
read:network |
the whole-network snapshot — not issued to ordinary partner keys |
Two-layer authorisation
- Who you are — Unkey + OpenFGA resolve
entity_idand permitted actions. - What you may see — the read-path filter (C1–C4) scopes every read.
Both are required. A valid key with a generous rate limit still cannot walk the wine or offer tables,
because the filter removes rows before serialisation and a record quota terminates page-walking.