Erori

Gestionarea erorilor

Coduri HTTP, rate limiting, strategii de retry și erori tipice

API-ul folosește coduri HTTP standard pentru semnalizarea erorilor. Toate erorile returnează JSON cu descrierea problemei.

Format eroare

{
  "statusCode": 400,
  "message": "Descrierea erorii",
  "error": "Bad Request"
}

Pentru erori de validare, message poate fi un array:

{
  "statusCode": 400,
  "message": [
    "announcementDescription must be at least 40 characters",
    "propertyType must be one of: residential, commercial, parking"
  ],
  "error": "Bad Request"
}

Coduri HTTP

CodTipDescriereReîncercare?
400Bad RequestParametri cerere incorecțiNu — corectează datele
401UnauthorizedProblemă cu cheia APINu — verifică cheia
403ForbiddenFără acces la resursăNu — verifică drepturile
404Not FoundResursa nu a fost găsităNu — verifică ID-ul
415Unsupported Media TypeContent-Type greșitNu — folosește application/json
422Unprocessable EntityToate operațiile bulk au eșuatNu — corectează datele
429Too Many RequestsLimită cereri depășităDa — după pauză
500Server ErrorEroare internăDa — cu exponential backoff

Cerințe pentru cereri

Content-Type

Toate cererile cu corp (POST, PUT, PATCH) trebuie să includă headerul Content-Type: application/json. Cererile cu alte tipuri de conținut primesc răspuns 415 Unsupported Media Type.

Limita dimensiunii corpului

Dimensiunea corpului cererii este limitată la 512 KB. Cererile care depășesc această limită primesc răspuns 413 Payload Too Large.

Rate Limiting

API-ul limitează numărul de cereri pentru protecție contra supraîncărcării. Fiecare răspuns conține headere cu informații despre limite.

Tip endpointLimită
Global (toate endpoint-urile)300 cereri / minut
Endpoint-uri bulk30 cereri / minut

Headere limite

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 295
X-RateLimit-Reset: 1705330800
HeaderDescriere
X-RateLimit-LimitMaximum cereri per perioadă
X-RateLimit-RemainingCâte cereri au mai rămas
X-RateLimit-ResetCând se resetează limita (Unix timestamp)

Ce să faci la 429

La depășirea limitei, API-ul returnează:

{
  "statusCode": 429,
  "message": "Too Many Requests"
}

Așteaptă până la timpul din X-RateLimit-Reset și repetă cererea:

Node.js
async function fetchWithRateLimit(url, options) {
  const response = await fetch(url, options);

  if (response.status === 429) {
    const resetTime = response.headers.get('X-RateLimit-Reset');
    const waitMs = (parseInt(resetTime) * 1000) - Date.now();
    await new Promise(r => setTimeout(r, Math.max(waitMs, 1000)));
    return fetch(url, options); // Repetă
  }

  return response;
}

Strategie retry

Când să repeți cererile

SituațieAcțiune
Erori 5xxRepetă cu exponential backoff
Erori 429Așteaptă până la X-RateLimit-Reset
Erori de rețeaRepetă cu backoff
Erori 4xxNu repeta — corectează cererea

Exponential backoff

La erori de server, mărește pauza între încercări:

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      // Eroare server — repetă
      if (response.status >= 500) {
        throw new Error(`Server error: ${response.status}`);
      }

      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;

      // Exponential backoff: 1s, 2s, 4s
      const delay = 1000 * Math.pow(2, attempt);
      await new Promise(r => setTimeout(r, delay));
    }
  }
}

// Utilizare
const response = await fetchWithRetry(
  'https://crm.rentix.md/api/v1/listings',
  {
    method: 'PUT',
    headers: { 'Authorization': 'ApiKey YOUR_API_KEY' },
    body: JSON.stringify(data)
  }
);

Erori tipice

Autentificare (400, 401, 403)

EroareCauzăSoluție
Multiple authentication methods providedAu fost trimise ambele headere Authorization și X-API-KeyFolosește doar un header de autentificare
API key is requiredCheia API nu a fost furnizatăAdaugă headerul Authorization: ApiKey YOUR_KEY
Invalid API keyCheia API este incorectă sau a fost revocatăVerifică valoarea cheii
Agency is suspendedContul agenției este suspendatContactează suportul
CRM is not enabled for this agencyAccesul CRM nu este activatContactează suportul pentru activarea CRM

Anunțuri (400)

EroareCauzăSoluție
Cannot provide both id and externalIdAi transmis ambii identificatoriFolosește unul singur
Must provide id or externalIdNu ai transmis identificator pentru actualizareAdaugă id sau externalId
External ID already linkedExternal ID este ocupat de alt anunțFolosește un ID unic
Minimum 3 photos requiredPentru publicare sunt necesare fotografiiÎncarcă minim 3 fotografii
Description too shortDescrierea are mai puțin de 40 caractereAdaugă mai mult text

Fișiere media (400)

EroareCauzăSoluție
Duplicate external IDExternal ID este deja folositFolosește un ID unic
File not foundFișierul nu existăVerifică fileId sau externalFileId
Invalid file typeFormat nesuportatFolosește JPEG, PNG, WebP sau HEIC
Upload URL expiredSigned URL a expirat (30 minute)Solicită un URL nou

Validare câmpuri

CodDescriere
STRING_TOO_SHORTStringul e mai scurt decât minimul
STRING_TOO_LONGStringul e mai lung decât maximul
NUMBER_TOO_SMALLNumărul e mai mic decât minimul
NUMBER_TOO_LARGENumărul e mai mare decât maximul
INVALID_ENUM_VALUEValoarea nu e din lista permisă
REQUIRED_FIELDCâmpul obligatoriu nu e completat

Exemplu: gestionarea tuturor cazurilor

Node.js
async function apiRequest(endpoint, data) {
  const url = `https://crm.rentix.md/api/v1${endpoint}`;
  const options = {
    method: 'PUT',
    headers: {
      'Authorization': 'ApiKey YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  };

  for (let attempt = 0; attempt < 3; attempt++) {
    const response = await fetch(url, options);

    // Succes
    if (response.ok) {
      return response.json();
    }

    // Rate limit — așteptăm și repetăm
    if (response.status === 429) {
      const resetTime = response.headers.get('X-RateLimit-Reset');
      const waitMs = (parseInt(resetTime) * 1000) - Date.now();
      await new Promise(r => setTimeout(r, Math.max(waitMs, 1000)));
      continue;
    }

    // Eroare server — repetăm cu backoff
    if (response.status >= 500) {
      await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
      continue;
    }

    // Eroare client — nu repetăm
    const error = await response.json();
    throw new Error(`API Error: ${JSON.stringify(error.message)}`);
  }

  throw new Error('Max retries exceeded');
}

Recomandări

  1. Logează erorile — salvează statusCode, message și timestamp pentru diagnosticare
  2. Nu ignora 4xx — sunt erori în datele tale, corectează-le
  3. Respectă rate limits — la 429 așteaptă întotdeauna timpul indicat
  4. Folosește exponential backoff — la 5xx nu bombarda serverul imediat
Copyright © 2026