Common API problems
Almost every API support case is one of about ten things. This is the list, in the order to check them, with the fix rather than the theory.
Read the error first
Every error comes back in the same shape:
{ "error": true, "message": "missing X-Revenexx-Tenant header" }
The message is usually specific enough to solve the problem on its own. Read
it before forming a theory. And take the X-Request-ID from the response
headers — it is what turns a support case from a conversation into an answer.
Status code to cause
| Code | Means | Usual cause | Fix |
|---|---|---|---|
400 | Malformed request | X-Revenexx-Tenant missing, or the body failed validation | Fix the request. Do not retry it unchanged |
401 | No valid credential | Key mistyped, truncated on copy, or revoked | Check the key. Reissue if in doubt |
403 | Authenticated, not allowed | The key's scope does not cover this capability | Add the specific scope — not * |
404 | No such resource here | The app is not installed on this tenant, or the path is wrong | Check openapi.json for this tenant |
429 | Rate limited | Too many requests, tenant-wide | Honour Retry-After, then back off |
502 | The implementing app or an upstream failed | Transient | Safe to retry with backoff |
Some apps answer a failed field validation with 422 rather than 400. Treat
them the same way: both mean the request was understood and rejected, and
neither should be retried unchanged.
400 and 404 are worth telling apart carefully.400 with "missing
X-Revenexx-Tenant" means the header never arrived — often stripped by a proxy
on the integrator's side. 404 on a path that definitely exists usually means
the app that provides it is not installed on this tenant, which is the classic
sandbox-versus-production difference. See Apps and the
Marketplace.401 right after creating a key
Almost always the copy, not the key. Long secrets get truncated by chat clients, spreadsheet cells and terminal wrapping. Revoke and reissue rather than debugging it; it takes two minutes and the alternative takes an afternoon.
The other cause: two credentials sent at once. Send eitherX-Revenexx-Api-Key or Authorization: Bearer …, never both.
403 on some calls and not others
This is a scope gap, and it is good news — the key works, it is not allowed to do this one thing. The message names the capability. Add that capability scope to the key, or issue a new key with it.
Resist the temptation to widen to * "for now". See Keys, scopes and
tenants.
The other 403 case: the app that implements the capability is not installed,
or the caller is not a member of the tenant.
429 that will not go away
One-off 429s are normal and mean your backoff is working. A steady stream
means something is designed wrong.
Check three things, in order:
- Is something looping? A job that makes one request per article is the usual culprit. It should be a bulk job — see Rate limits, quotas and fair use.
- Is something else running at the same time? The limit is per tenant, not per key. Your BI extract and your ERP sync compete, and so does your storefront.
- Does the client back off with jitter? Parallel workers retrying in
lockstep recreate the spike that caused the
429.
The webhook that never arrives
Work down this list. It is in the order that resolves fastest.
- Did the event happen? Look in Events › Event Stream. If the event is not there, this is not a webhook problem.
- Does anything subscribe to that topic? The event's Routed to section answers it. "No destination subscribes to this topic yet" is the most common answer, and the fix is a subscription, not a debugging session.
- Is the destination enabled? A destination that failed persistently is disabled automatically. Re-enabling does not replay what was missed.
- What do the delivery attempts say? Persistent
4xxis your payload or credentials; persistent5xxis their system; timeouts mean the receiver is too slow. - Is the receiver reachable from the internet at all? See the firewall section below.
- Did it arrive and get discarded? A receiver that rejects an unverified
signature answers
401, which looks like a delivery failure from your side and is actually a verification failure on theirs.
The signature that never matches
Four causes, in order of how often they turn out to be the answer.
1. The body was re-serialised. By far the most common. The signature covers the raw request bytes, exactly as received. A framework that parses JSON and re-encodes it before the verification step changes whitespace or key order, and nothing will ever match. Capture the raw body before any parsing.
2. The wrong secret. A secret copied from the wrong destination, or one that was rotated on one side only.
3. Rotation not handled. During a rotation the signature header can carry more than one comma-separated signature. A receiver that reads only the first one will reject half the deliveries. Accept the delivery if any signature matches.
4. Encoding. HMAC-SHA256, hexadecimal, compared against the value after
v0=. Base64 will not match hex.
Clock skew
If the receiver checks the delivery timestamp — and it should — a clock that has
drifted rejects perfectly valid deliveries. The symptom is distinctive:
everything fails, all at once, with no configuration change, and the failures
are 401 from the receiver rather than errors from the platform.
Fix it at the source: run NTP on the receiving host. Do not widen the tolerance window to compensate, because the window is what prevents an old captured delivery being replayed at you later.
The same applies to signed download URLs from an export: they are short-lived, and a machine whose clock is wrong will believe a valid URL has expired.
Firewall and egress
The problem that always presents as "the API is broken" and is always a network rule.
Inbound to your receiver. A webhook destination has to be reachable from the
public internet, over HTTPS, with a certificate that validates. Endpoints behind
a corporate VPN, on a .local name, or on a private IP range will never
receive anything. Nor will an endpoint that requires a client certificate.
Outbound from your systems. A machine calling api.revenexx.com needs
outbound HTTPS on port 443. In a Mittelstand network that is often blocked by
default, and the symptom is a connection timeout rather than an HTTP error.
Proxies that rewrite requests. A corporate proxy that strips unknown headers
will remove X-Revenexx-Tenant, and you get 400 with a message saying the
header is missing — while the integrator is looking at code that clearly sets
it. This is the hardest one to spot and the message is the clue.
A three-minute triage that separates all of these:
| Test | If it works | If it fails |
|---|---|---|
curl from your own laptop with the key | The key and the scopes are fine | The credential is the problem |
The same curl from the integrator's server | The network path is fine | Egress, DNS or proxy |
| A test delivery to their endpoint | Inbound works | Their firewall, TLS or certificate |
Do all three before anyone opens a ticket. It removes most cases immediately and tells you whose problem the rest are.
Degraded, not broken
Two response headers are worth knowing about because they explain otherwise puzzling behaviour:
X-Capability-Degraded— a fallback implementation served the request. It worked, but not from the usual path. Sustained degradation is worth a support case even though nothing is erroring.X-Cache: HIT— the response was cached. If a write does not appear to take effect on the next read, this is the first thing to check.
When to open a support case
You have checked the status code and its message, confirmed the key and its scopes, confirmed the network path from the calling machine, and the failure is reproducible. Bring:
- The
X-Request-IDfrom a failing response. - The tenant slug, the key name (never the secret), and the exact path and method.
- When it started, and what changed around then.
- For a webhook: the event id and the destination name.
Next
- Monitor your integrations — catching these before someone reports them.
- Handling API changes — the failures that were announced in advance.
Monitor your integrations
The four logs worth reading, the three alerts worth setting, and the daily five minutes that catches an integration problem before a buyer does.
Handling API changes
What 'additive' guarantees you, where changes are announced, how long a deprecation window is, and how to test the next version before it is the only version.