Developers
Everything we sell is reachable by API: the green-coffee catalog, lot detail, samples, quotes and trade accounts. Reads need no credentials. There is no sales call to book — accounts are self-serve and a sandbox is always on.
Start here
| Contract | api.gonzalezbrothers.coffee/openapi.json (OpenAPI 3.1) |
|---|---|
| Production | https://api.gonzalezbrothers.coffee |
| Sandbox | https://stage.api.gonzalezbrothers.coffee — same contract, its own data and accounts, always on. Build against it first: curl https://stage.api.gonzalezbrothers.coffee/health answers {"success":true,…}, and GET / with Accept: application/json returns an index of the endpoints. |
| Agent guide | gonzalezbrothers.coffee/agents.md |
| Permissions | oauth-protected-resource (RFC 9728, scopes_supported) |
| Versioning | deprecation policy — /api/v1 is current |
Quickstart: read the catalog (no key)
curl https://api.gonzalezbrothers.coffee/api/v1/catalog/full
curl https://api.gonzalezbrothers.coffee/api/v1/lots/{id}
curl https://gonzalezbrothers.coffee/apps/shop/channels/green # what is on sale right now, with per-kg prices
Every lot carries its number, farm, variety, process, cupping score, price and stock. /catalog/full is the priced catalog with supplier contact details redacted.
Command line
The official CLI wraps the same contract — no key needed for reads, --sandbox for the stage API. Node 20+, zero dependencies, gonzalezbrothers-cli on npm.
npx gonzalezbrothers-cli catalog --full
npx gonzalezbrothers-cli channel green
npx gonzalezbrothers-cli lot {id} --sandbox
npx gonzalezbrothers-cli --help
Self-serve account
Sign up over the API, confirm the email code, log in, and send the access token as a bearer. No approval step.
curl -X POST https://stage.api.gonzalezbrothers.coffee/api/v1/auth/signup \
-H 'content-type: application/json' \
-d '{"email":"you@example.com","password":"…","firstName":"…","lastName":"…","company":"…","privacyPolicyAccepted":true}'
curl -X POST https://stage.api.gonzalezbrothers.coffee/api/v1/auth/confirm -H 'content-type: application/json' -d '{"email":"you@example.com","code":"123456"}'
curl -X POST https://stage.api.gonzalezbrothers.coffee/api/v1/auth/login -H 'content-type: application/json' -d '{"email":"you@example.com","password":"…"}'
curl https://stage.api.gonzalezbrothers.coffee/api/v1/orders -H "Authorization: Bearer $ACCESS_TOKEN"
Scopes
Each operation in the contract names the scope it needs. An account token holds every authenticated scope; catalog.enriched (full supplier records) comes with a confirmed trade account. Machine-to-machine clients (OAuth 2.0 client credentials against the same scopes) are issued per integration — ask us at contact with what you are building.
catalog.read,catalog.enrichedorders.read,orders.writesamples.read,samples.writeshortlist.read,shortlist.writeaccount.read,account.write
A missing scope answers 403 with WWW-Authenticate: Bearer error="insufficient_scope", scope="…" naming what to request.
Buying through the shop
Roasted bags go through the normal cart and checkout (or UCP: https://gonzalezbrothers.coffee/.well-known/ucp). Roasted kilos and green sacks never do — request a quote and a person prices the shipping:
curl -X POST https://gonzalezbrothers.coffee/apps/shop/quotes -H 'content-type: application/json' -d '{"channel":"green","lines":[{"lotNumber":"…","size":"sack","quantity":1}],"name":"…","email":"…","addressLine1":"…","city":"…","postcode":"…","country":"GB"}'
curl -X POST https://gonzalezbrothers.coffee/apps/shop/samples -H 'content-type: application/json' -d '{"lotNumbers":["…"],"sampleType":"green","name":"…","email":"…","company":"…","addressLine1":"…","city":"…","postcode":"…","country":"GB"}'
Limits and errors
- 300 requests a minute per IP across the API, tighter on the forms; every response carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset. A429carriesRetry-After. - Errors are RFC 7807
application/problem+json. Unknown paths are a real404whose body links back to the contract. - Prices are in GBP. Current prices.