Dike logoDocs

All error responses from Dike follow the RFC 7807 Problem Details specification with Content-Type: application/problem+json; charset=utf-8.

{
  "type": "https://dike.it.com/errors/citation_not_found",
  "title": "Citation Not Found",
  "status": 404,
  "detail": "Citation 'القانون رقم 999 لسنة 2099' parsed successfully but does not exist in the indexed corpus.",
  "code": "citation_not_found",
  "parsed": {
    "doc_type": "legislation",
    "number": "999",
    "year": 2099
  }
}

Always Match on 'code'

Never branch your code on HTTP status alone or attempt to regex detail/title. The code string is guaranteed stable across all API versions.


Complete Error Code Catalog

HTTP StatusMachine codeTrigger ConditionRecommended Remediation
400 / 422validation_errorRequest payload missing required fields (query, question, citation) or parameter outside valid bounds (top_k > 50, depth > 3).Check schema definitions in API Reference.
401unauthorizedMissing Authorization header, invalid token format, or revoked API key.Confirm key begins with dike_live_ and is present in dashboard.
403plan_requiredAttempting to access an endpoint not permitted by current plan (e.g. POST /v1/reason on Free tier).Upgrade account to Pay As You Go in Developer Dashboard.
404not_foundTarget canonical_id does not exist on GET /v1/document/{id} or POST /v1/graph/traverse.Verify canonical ID format against /v1/search or /v1/cite.
404citation_not_foundCitation parsed cleanly into legal parameters on POST /v1/cite, but no matching statute exists in database.Check Jurisdictions & Coverage matrix.
422citation_unparseableString passed to POST /v1/cite did not match any recognized Arabic legal citation grammar.Inspect detail for attempted normalized form; reformat input text.
429rate_limitedExceeded per-minute sliding window rate limit.Read X-RateLimit-Reset and backoff with jitter.
503upstream_unavailableDownstream search index, document store, or reasoning service is temporarily unreachable.Retry request with exponential backoff (e.g. 1s, 2s, 4s).

Production Error Handling Snippets

import time
import httpx

def robust_dike_call(url: str, payload: dict, api_key: str, max_retries: int = 3):
    headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
    
    for attempt in range(max_retries):
        try:
            response = httpx.post(url, headers=headers, json=payload, timeout=15.0)
            
            if response.is_success:
                return response.json()
            
            problem = response.json()
            error_code = problem.get("code", "unknown_error")
            
            match error_code:
                case "rate_limited":
                    reset_time = int(response.headers.get("X-RateLimit-Reset", time.time() + 10))
                    sleep_sec = max(1, reset_time - int(time.time()))
                    print(f"Rate limited. Waiting {sleep_sec}s...")
                    time.sleep(sleep_sec)
                    continue
                
                case "upstream_unavailable":
                    backoff = 2 ** attempt
                    print(f"Upstream blip (503). Backing off {backoff}s...")
                    time.sleep(backoff)
                    continue
                
                case "citation_not_found":
                    print(f"Citation not in corpus: {problem.get('detail')}")
                    return None
                
                case "plan_required":
                    raise PermissionError("Plan upgrade required for /v1/reason.")
                
                case _:
                    raise RuntimeError(f"Dike API Error [{response.status_code}] {error_code}: {problem.get('detail')}")
                    
        except httpx.RequestError as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)
            
    raise RuntimeError("Max retries exceeded.")
interface ProblemDetails {
  type: string;
  title: string;
  status: number;
  detail: string;
  code: string;
}

async function callDikeSafe<T>(endpoint: string, body: any): Promise<T> {
  const apiKey = process.env.DIKE_API_KEY;
  const res = await fetch(`https://api.dike.it.com${endpoint}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (res.ok) {
    return (await res.json()) as T;
  }

  const problem: ProblemDetails = await res.json().catch(() => ({
    type: 'unknown',
    title: res.statusText,
    status: res.status,
    detail: 'Non-JSON error response from server',
    code: 'unknown_error',
  }));

  switch (problem.code) {
    case 'rate_limited': {
      const reset = res.headers.get('X-RateLimit-Reset');
      throw new Error(`Rate limited. Window resets at: ${reset}`);
    }
    case 'plan_required':
      throw new Error('This endpoint requires a Pay As You Go subscription.');
    case 'citation_not_found':
      console.warn('Citation parsed but not indexed in corpus:', problem.detail);
      return null as T;
    default:
      throw new Error(`Dike Error (${problem.code}): ${problem.detail}`);
  }
}

On this page