Fouten
Sursa gebruikt HTTP-statuscodes om aan te geven of een request is geslaagd, en een stabiele foutcode om aan te geven waarom niet. Elke foutresponse heeft dezelfde vorm:
{
"detail": "the cursor is malformed or was issued for different filters",
"error": {
"code": "api.cursor_invalid",
"message": "the cursor is malformed or was issued for different filters",
"details": {"parameter": "cursor"},
"request_id": "01JB7Q2M4X9V3K8T5N6P0R1S2A",
"doc_url": "https://developers.sursa.com/errors/api.cursor_invalid"
}
}
| Veld | Betekenis |
|---|---|
error.code | Stabiele code in de vorm <area>.<reason>. Laat je code hierop vertakken. |
error.message | Een leesbare Engelse uitleg. Die kan op elk moment anders worden geformuleerd; parseer hem niet. |
error.details | Gestructureerde gegevens over de fout, zoals de parameter, een limiet of wanneer je het opnieuw kunt proberen. De velden hangen af van de code. |
error.request_id | De ID van dit request, gelijk aan de responseheader X-Request-Id. |
error.doc_url | De pagina over deze code op dit portaal. |
detail | De eerdere vorm van de fout, behouden voor bestaande integraties. Nieuwe code leest beter error. |
Elke code heeft een eigen pagina onder Foutcodes, met de HTTP-status, de velden van details en de
endpoints die de code teruggeven. Op de pagina van elk endpoint in de API-referentie staan de codes die
dat endpoint kan teruggeven.
HTTP-statussen
| Status | Betekenis |
|---|---|
200, 201, 202, 204 | Het request is geslaagd. 202 betekent dat het is geaccepteerd en nog wordt verwerkt. |
400 | Het request is onjuist opgebouwd: een ongeldige parameter, cursor, metadata of Idempotency-Key. Corrigeer het request. |
401 | Geen geldige sleutel. Zie Authenticatie. |
402 | Een limiet van het abonnement van de organisatie is bereikt, zoals het aantal kaarten of de opslag. |
403 | De sleutel is geldig, maar mag dit niet doen: er ontbreekt een rol, een scope of een functie van het abonnement. |
404 | Het object bestaat niet, of de sleutel mag het niet zien. |
409 | Het request is in strijd met de huidige toestand: een dubbele external_id, een open synchronisatie, een request met dezelfde Idempotency-Key dat nog loopt. |
410 | Het object is verlopen, zoals een upload na 24 uur, of de route is buiten gebruik gesteld. |
413 | De body of het bestand is te groot. |
415 | Het bestandstype wordt niet ondersteund, of de inhoud past niet bij de naam. |
422 | Het request is goed opgebouwd, maar ongeldig: een ontbrekend veld of een waarde buiten het bereik. |
429 | Te veel requests, of een quotum is op. Zie Snelheidslimieten en quota. |
500, 502, 503, 504 | Een probleem aan de kant van Sursa. Probeer het later opnieuw. |
Validatiefouten
Bij 422 met de code validation.failed somt detail elk veld op dat niet door de
validatie kwam, elk met zijn locatie:
{
"detail": [
{"loc": ["body", "title"], "msg": "String should have at least 1 character", "type": "string_too_short"}
],
"error": {"code": "validation.failed", "message": "request validation failed", "request_id": "01JB7…"}
}
Welke fouten je opnieuw probeert
| Fout | Opnieuw proberen? |
|---|---|
| Netwerkfout of time-out, geen response | Ja, met dezelfde Idempotency-Key. |
429 | Ja, na het aantal seconden in Retry-After. |
500, 502, 503, 504 | Ja, met exponentiële backoff: 1 s, 2 s, 4 s… tot een minuut, met willekeurige jitter. |
409 api.idempotency_in_progress | Ja, na Retry-After: het eerste request met deze sleutel loopt nog. |
Elke andere 4xx | Nee. Hetzelfde request mislukt opnieuw; corrigeer het eerst. |
Probeer POST- en PATCH-requests alleen opnieuw met een Idempotency-Key, zodat
een nieuwe poging na een verloren response geen tweede object kan maken. GET, PUT en DELETE kun je zonder meer
opnieuw proberen.
// Retries a request on network errors, 429 and 5xx. The same Idempotency-Key is sent on every attempt.
async function withRetries(send, attempts = 5) {
for (let attempt = 1; ; attempt++) {
let response;
try {
response = await send();
} catch (error) {
if (attempt >= attempts) throw error;
}
if (response && response.status !== 429 && response.status < 500) return response;
if (attempt >= attempts) return response;
const retryAfter = Number(response?.headers.get("Retry-After"));
const backoff = Math.min(60, 2 ** (attempt - 1)) * (0.8 + Math.random() * 0.4);
await new Promise((resolve) => setTimeout(resolve, 1000 * (retryAfter || backoff)));
}
}
const key = crypto.randomUUID();
const response = await withRetries(() =>
fetch("https://api.sursa.com/v1/cards/text", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SURSA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": key,
},
body: JSON.stringify({ title: "Refund policy", body_markdown: "Refunds take 14 days." }),
}),
);Een probleem melden
Elke response, geslaagd of niet, heeft een header X-Request-Id, en elke fout heeft dezelfde waarde in
error.request_id. Log die samen met je eigen gegevens over het request. Neem je over een request contact op met de
support, stuur dan de request-ID mee: daarmee is het record van dat request direct te vinden.
Omgaan met codes die je niet kent
Er kunnen in elke versie van de API nieuwe foutcodes verschijnen. Behandel een onbekende code op basis van zijn
HTTP-status: een onbekende 4xx als een request dat in deze vorm niet zal slagen, een onbekende 5xx als een
tijdelijk probleem.