Dike logoDocs

Execute grounded legal reasoning over retrieved MENA legal corpora. Every citation emitted in the generated answer is strictly checked against retrieved statutes before reaching the client.

POST https://api.dike.it.com/v1/reason
Authorization: Bearer dike_live_xxxxxxxx
Content-Type: application/json

Plan Requirement

POST /v1/reason requires an active Pay As You Go or Enterprise plan. Calling on a Free tier returns 403 with code: plan_required.

Rendering diagram...

Request Parameters

{
  "question": "ما هي التزامات المؤجر في صيانة العين المؤجرة وفقاً للقانون المصري؟",
  "filters": {
    "jurisdiction": "EG",
    "status": ["in_force"]
  },
  "top_k": 12,
  "stream": false,
  "language": "ar"
}

Body Schema

ParameterTypeDefaultConstraintsDescription
questionstringRequired5–2000 charsThe natural language legal question in Arabic or English.
filtersobjectnullSame schema as /v1/searchOptional filters (jurisdiction, doc_type, year_from, year_to, status).
top_kinteger124–30Number of legal chunks retrieved into the reasoning context window.
streambooleanfalsetrue or falseWhen true, returns a Server-Sent Events (text/event-stream) stream.
languagestring"ar""ar" or "en"Language of the generated synthesis.

Synchronous Code Examples

curl -X POST https://api.dike.it.com/v1/reason \
  -H "Authorization: Bearer $DIKE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "هل يجوز للمستأجر حبس الأجرة إذا امتنع المؤجر عن إجراء الترميمات الضرورية؟",
    "filters": {"jurisdiction": "EG"},
    "top_k": 12
  }'
import os
import httpx

client = httpx.Client(
    base_url="https://api.dike.it.com",
    headers={"Authorization": f"Bearer {os.getenv('DIKE_API_KEY')}"},
    timeout=30.0,
)

response = client.post(
    "/v1/reason",
    json={
        "question": "هل يجوز للمستأجر حبس الأجرة إذا امتنع المؤجر عن إجراء الترميمات الضرورية؟",
        "filters": {"jurisdiction": "EG"},
        "top_k": 12,
    },
)

# Check for weak grounding header
is_weak = response.headers.get("X-Dike-Grounding") == "weak"
data = response.json()

print(f"Grounding Status: {'WEAK' if is_weak else 'STRONG'}")
print("Answer:\n", data["answer"])
print(f"Citations Verified: {len(data['citations'])}")
const apiKey = process.env.DIKE_API_KEY;

async function askLegalQuestion() {
  const res = await fetch('https://api.dike.it.com/v1/reason', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      question: 'هل يجوز للمستأجر حبس الأجرة إذا امتنع المؤجر عن إجراء الترميمات الضرورية؟',
      filters: { jurisdiction: 'EG' },
      top_k: 12,
    }),
  });

  const isWeak = res.headers.get('X-Dike-Grounding') === 'weak';
  const data = await res.json();
  
  return { ...data, isWeakGrounding: isWeak };
}

Streaming Protocol (stream: true)

When stream: true is passed, the connection switches to Content-Type: text/event-stream.

Stream Events Lifecycle

  1. Token Chunks (message): Emits raw answer tokens. Token buffers prevent partial citation tags from splitting across chunk boundaries.
  2. Citations Payload (citations): Emits a final event containing all verified citation metadata and grounding stats.
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive

data: {"token": "يلتزم "}

data: {"token": "المؤجر "}

data: {"token": "بإجراء الترميمات الضرورية [1] "}

event: citations
data: {"citations": [{"marker": 1, "canonical_id": "eg-leg-1948-131", "article_no": "567", "citation_string": "المادة 567 من القانون المدني", "snippet": "...", "verified": true}], "grounding": {"retrieved": 12, "used": 1, "dropped_unverified_refs": 0}}

data: [DONE]

TypeScript SSE Streaming Client

async function streamReasoning(question: string) {
  const response = await fetch('https://api.dike.it.com/v1/reason', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.DIKE_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ question, stream: true }),
  });

  const reader = response.body?.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  while (reader) {
    const { done, value } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    
    // Process SSE lines
    const lines = buffer.split('\n');
    buffer = lines.pop() || '';

    for (const line of lines) {
      if (line.startsWith('data: ') && !line.includes('[DONE]')) {
        const json = JSON.parse(line.slice(6));
        if (json.token) process.stdout.write(json.token);
      }
    }
  }
}

Response Schema (Non-Streaming)

{
  "answer": "وفقاً لأحكام القانون المدني المصري رقم 131 لسنة 1948، يلتزم المؤجر بصيانة العين المؤجرة وإجراء الترميمات الضرورية [1]. فإذا أخل المؤجر بذلك بعد إنذاره، يجوز للمستأجر استئذان القضاء لإجراء الترميمات وخصمها من الأجرة أو فسخ الإيجار [1].",
  "citations": [
    {
      "marker": 1,
      "canonical_id": "eg-leg-1948-131",
      "article_no": "567",
      "citation_string": "المادة 567 من القانون المدني رقم 131 لسنة 1948",
      "snippet": "على المؤجر أن يتعهد العين المؤجرة بالصيانة لتبقى على الحالة التي سلمت بها...",
      "verified": true
    }
  ],
  "grounding": {
    "retrieved": 12,
    "used": 1,
    "dropped_unverified_refs": 0
  },
  "took_ms": 2910
}

Error Codes

StatusCodeCause
401unauthorizedMissing or invalid API key
403plan_requiredAttempted to call /v1/reason on a Free plan
422validation_errorMissing question or parameter constraints violated
429rate_limitedExceeded 10 req/min limit on Pay As You Go
503upstream_unavailableDownstream LLM inference service temporary failure

On this page