Errors
Sursa fa servir els codis d’estat HTTP per indicar si una sol·licitud ha anat bé, i un codi d’error estable per indicar per què no. Totes les respostes d’error tenen la mateixa forma:
{
"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"
}
}
| Camp | Significat |
|---|---|
error.code | Codi estable amb la forma <area>.<reason>. Baseu-hi les decisions del vostre codi. |
error.message | Una explicació llegible en anglès. Se’n pot canviar la redacció en qualsevol moment; no l’analitzeu. |
error.details | Dades estructurades sobre l’error, com ara el paràmetre, un límit o quan cal reintentar. Els seus camps depenen del codi. |
error.request_id | L’ID d’aquesta sol·licitud, el mateix que la capçalera de resposta X-Request-Id. |
error.doc_url | La pàgina d’aquest codi en aquest portal. |
detail | La forma anterior de l’error, que es manté per a les integracions existents. El codi nou ha de llegir error. |
Cada codi té la seva pàgina a Codis d’error, amb el seu estat HTTP, els camps de details i els punts
finals que el retornen. La pàgina de cada punt final a la referència de l’API enumera els codis que
aquest punt final pot retornar.
Estats HTTP
| Estat | Significat |
|---|---|
200, 201, 202, 204 | La sol·licitud ha anat bé. 202 vol dir que s’ha acceptat i encara s’està processant. |
400 | La sol·licitud està mal formada: un paràmetre, un cursor, unes metadata o una Idempotency-Key incorrectes. Corregiu la sol·licitud. |
401 | No hi ha cap clau vàlida. Vegeu Autenticació. |
402 | S’ha arribat a un límit del pla de l’organització, com ara el nombre d’entrades o l’emmagatzematge. |
403 | La clau és vàlida, però no té permís per fer això: hi falta un rol, un àmbit o una funció del pla. |
404 | L’objecte no existeix o la clau no el pot veure. |
409 | La sol·licitud entra en conflicte amb l’estat actual: un external_id duplicat, una sincronització oberta, una sol·licitud amb la mateixa Idempotency-Key que encara s’està executant. |
410 | L’objecte ha caducat, com ara una pujada després de 24 hores, o la ruta s’ha retirat. |
413 | El cos o el fitxer és massa gran. |
415 | El tipus de fitxer no s’admet o el seu contingut no correspon al nom. |
422 | La sol·licitud està ben formada, però no és vàlida: falta un camp o un valor és fora de l’interval permès. |
429 | Massa sol·licituds o una quota esgotada. Vegeu Límits de freqüència i quotes. |
500, 502, 503, 504 | Un problema a la banda de Sursa. Torneu-ho a provar més tard. |
Errors de validació
Per a 422 amb el codi validation.failed, detail enumera tots els camps que han
fallat, cadascun amb la seva ubicació:
{
"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…"}
}
Quins errors cal reintentar
| Error | Cal reintentar? |
|---|---|
| Error de xarxa o temps d’espera esgotat, sense resposta | Sí, amb la mateixa Idempotency-Key. |
429 | Sí, després del nombre de segons de Retry-After. |
500, 502, 503, 504 | Sí, amb espera exponencial: 1 s, 2 s, 4 s… fins a un minut, amb variació aleatòria. |
409 api.idempotency_in_progress | Sí, després de Retry-After: la primera sol·licitud amb aquesta clau encara s’està executant. |
Qualsevol altre 4xx | No. La mateixa sol·licitud tornarà a fallar; primer corregiu-la. |
Reintenteu les sol·licituds POST i PATCH només amb una Idempotency-Key, perquè
un reintent després d’una resposta perduda no pugui crear un segon objecte. GET, PUT i DELETE es poden
reintentar sense risc tal com són.
// 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." }),
}),
);Informar d’un problema
Cada resposta, correcta o no, té una capçalera X-Request-Id, i cada error té el mateix valor a error.request_id.
Deseu-lo als vostres registres juntament amb la sol·licitud. Quan contacteu amb el servei d’assistència per una
sol·licitud, envieu-ne l’ID: porta directament a l’anotació d’aquella sol·licitud.
Codis que no coneixeu
Poden aparèixer codis d’error nous en qualsevol versió de l’API. Tracteu un codi desconegut segons el seu estat HTTP:
un 4xx desconegut, com una sol·licitud que no tindrà èxit tal com és; un 5xx desconegut, com un problema temporal.