Reference · Gateway
Gateway HTTP spec
What a buyer (or their agent) sends, what the gateway sends back, and exactly what every error code means. For the seller-side setup, see /app.
URL
https://www.lemoncake.xyz/g/<shortId>
shortIdis the 8-character base32 ID printed in the seller's Gateway pane on /app. The gateway is method-agnostic — GET / POST / PUT / PATCH / DELETEare all forwarded to the seller's origin URL with the same method and body.
Authentication
Every paid request must carry a Pay Token JWT:
POST https://www.lemoncake.xyz/g/abc12345 HTTP/1.1
Host: www.lemoncake.xyz
Authorization: Bearer eyJhbGciOiJIUzI1NiI…
Content-Type: application/json
{ "query": "your upstream payload" }JWTs are HS256-signed. The gateway verifies the signature, looks up the token row in Postgres, and rejects on revoked / expired / exhausted / over-budget. See Pay Token spec for the full payload format.
Successful response
The upstream's body and most headers are streamed back verbatim (hop-by-hop headers are stripped). Two LemonCake trace headers are added so buyers can audit charges:
HTTP/2 200 OK
content-type: application/json
x-lemoncake-charge: 0.01
x-lemoncake-upstream-ms: 17
{ "result": "…" }| Header | Meaning |
|---|---|
| x-lemoncake-charge | USD amount debited from your Pay Token's budget for this call. |
| x-lemoncake-upstream-ms | Time the upstream took to respond. Gateway-side overhead is ~10ms (Tokyo region). |
Error responses
All errors return a JSON body of { "error": "<code>" }. No Pay Token charge is recorded on any non-2xx/3xx outcome.
| Status | error code | Meaning |
|---|---|---|
| 401 | missing_pay_token | No Authorization header / wrong scheme. Attach `Authorization: Bearer <jwt>`. |
| 401 | invalid_pay_token | JWT signature or claims invalid. Likely tampered or signed with a different LC_JWT_SECRET. |
| 401 | token_expired | The Pay Token's expiry has passed. Ask the seller to issue a fresh one. |
| 402 | spend_cap_exceeded | Pay Token's budget would go negative on this call. Request a top-up. |
| 402 | token_exhausted | Pay Token has hit its max_calls cap. |
| 403 | token_revoked | Seller manually revoked this Pay Token. |
| 403 | token_endpoint_mismatch | JWT was issued for a different endpoint than the one you're calling. |
| 404 | endpoint_not_found | shortId doesn't exist (typo, or the seller deleted it). |
| 429 | rate_limit_exceeded | More than `rate_limit` successful calls in the last 60s for this endpoint. |
| 503 | endpoint_paused | Seller temporarily paused this endpoint. Try again later. |
| 502 | upstream_unreachable | Gateway couldn't reach the seller's origin. Pay Token is NOT debited. |
| 503 | backend_not_configured | Gateway env vars missing on the LemonCake side. Email contact@aievid.com. |
Refund semantics
The gateway only charges your Pay Token when the upstream returns 2xx / 3xx / 4xx. On 5xx or network failure, the call is logged in the blocked log under upstream_error and your token is notdebited. Buyers never pay for the seller's origin outage.
CORS
The gateway returns permissive CORS so browser-side agents work out of the box:
Access-Control-Allow-Origin: <Origin echo> Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Allow-Headers: Authorization, Content-Type Access-Control-Expose-Headers: x-lemoncake-charge, x-lemoncake-upstream-ms Access-Control-Max-Age: 86400
Preflight OPTIONS returns 204 without authentication or DB lookups.
// Browser-side example
const res = await fetch("https://www.lemoncake.xyz/g/abc12345", {
method: "POST",
headers: { "Authorization": "Bearer " + PAY_TOKEN_JWT },
body: JSON.stringify({ query: "…" }),
});
console.log(res.headers.get("x-lemoncake-charge")); // "0.01"Header forwarding rules
The gateway forwards almost all request headers to the upstream, with these exceptions:
| Behaviour | Headers |
|---|---|
| Stripped (hop-by-hop) | host, connection, content-length, transfer-encoding, keep-alive, proxy-authenticate, proxy-authorization, te, trailer, upgrade |
| Replaced | Authorization — your Pay Token JWT is replaced with the seller's stored upstream_auth header (if any) |
| Never forwarded | Cookie — buyer-side cookies are not leaked to the seller's origin |
Charging math
For every successful call:
gross = endpoint.price_per_call
fee = (in the seller's first 3,000 calls / UTC month) → 0
(after 3,000) → gross * 0.03
net = gross - feeThe buyer's Pay Token decrements by grossregardless of free-tier state — the free tier affects LemonCake's cut, not the buyer's spend. Per-call breakdown is logged in lc_test_runs, visible on the seller's Usage Ledger pane.
Next
- Pay Token spec → JWT claims, lifecycle, revocation
- Open /app → Create your own paid-access endpoint
- Email us → for design-partner access or integration help

