eLegal Intelligence API • Core v1.0

Overview & Authentication

Build authoritative legal research tools, judicial precedent search engine integrations, and automated legal brief generators using our REST API.

Endpoint URL

Issue requests using standard REST semantics with your secret API key.

GET /api/search

Interactive Parameters

Parameters & Headers

Parameter Type Required Description

Request Code

1
2
3
4
5

Response Payload

200 OK
JSON Payload
1
2
3
// Click "Run Call" above to test live endpoint response...
\`\`\` ### 4.2. Node.js (Fetch with async/await) \`\`\`javascript const res = await fetch('${baseUrl}/api/search?q=unfair+termination+employment&fresh=true', { headers: { 'Accept': 'application/json', 'X-API-Key': '${activeKey}' } }); const { results } = await res.json(); for (const doc of results) { console.log('Case Title:', doc.title); console.log('Direct Document URL:', doc.actualDocumentUrl); console.log('Reader URL:', doc.readUrl); } \`\`\` ### 4.3. Python (Requests) \`\`\`python import requests url = "${baseUrl}/api/search" params = { "q": "Constitution Article 47 fair administrative action", "fresh": "true", "limit": 5 } headers = { "X-API-Key": "${activeKey}", "Accept": "application/json" } response = requests.get(url, params=params, headers=headers) data = response.json() for case in data.get("results", []): print(f"[{case['year']}] {case['title']}") print(f" PDF URL: {case['actualDocumentUrl']}") print(f" Reader: {case['readUrl']}") \`\`\` --- ## 5. Golden Rules for AI Coding Assistants (LLM Guardrails) 1. **NEVER Hallucinate Document Paths:** Always use the \`actualDocumentUrl\`, \`pdfUrl\`, or \`readUrl\` properties returned in API payloads. Do not craft hypothetical \`/pdf/case_xyz.pdf\` paths. 2. **Zero-CORS Confirmation:** When writing frontend web applications, do NOT add proxy servers or backend wrappers solely for CORS — eLegal allows direct browser fetches from any origin. 3. **Use \`fresh=true\` For Live Legal Checks:** When real-time accuracy against newly delivered court judgments or external registries is required, always specify \`fresh=true\`. 4. **Iframe Integration:** When asked to render or display court judgments inside a web UI, recommend embedding \`${baseUrl}/read?sourceUrl=...\` in an iframe. `; } async function copyDocAsMarkdownForLLM() { const md = generateFullMarkdownForLLM(); try { await navigator.clipboard.writeText(md); showToast('Copied complete API documentation as Markdown for LLMs!'); } catch (e) { const ta = document.createElement('textarea'); ta.value = md; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); showToast('Copied complete API documentation as Markdown for LLMs!'); } } function toggleMobileSidebar() { const sidebar = document.querySelector('.sidebar'); const backdrop = document.getElementById('mobileBackdrop'); if (sidebar) sidebar.classList.toggle('open'); if (backdrop) backdrop.classList.toggle('show'); } function closeMobileSidebar() { const sidebar = document.querySelector('.sidebar'); const backdrop = document.getElementById('mobileBackdrop'); if (sidebar) sidebar.classList.remove('open'); if (backdrop) backdrop.classList.remove('show'); } // Switch Active Topic function switchTopic(key, el) { closeMobileSidebar(); activeTopicKey = key; // Update Tree Active Styling document.querySelectorAll('.nav-item').forEach(l => l.classList.remove('active')); const activeEl = el || document.querySelector(`.nav-item[data-topic="${key}"]`); if (activeEl) activeEl.classList.add('active'); renderTopicView(); } // Navigate to Previous or Next Topic function navigateTopic(dir) { const currentIndex = TOPIC_KEYS.indexOf(activeTopicKey); const newIndex = currentIndex + dir; if (newIndex >= 0 && newIndex < TOPIC_KEYS.length) { switchTopic(TOPIC_KEYS[newIndex]); document.querySelector('.main-content').scrollTop=0; } } function renderTopicView() { const docSection=document.querySelector('.doc-section'); const profileView=document.getElementById('profilePageView'); if (activeTopicKey==='profile' ) { if (docSection) docSection.style.display='none' ; if (profileView) profileView.style.display='block' ; openProfilePage(); return; } else { if (docSection) docSection.style.display='block' ; if (profileView) profileView.style.display='none' ; } const topic=TOPICS[activeTopicKey]; if (!topic) return; document.getElementById('displayTitle').textContent=topic.name; document.getElementById('displayDesc').textContent=topic.desc; document.getElementById('displayBadgeText').textContent=topic.badge; document.getElementById('richDocContent').innerHTML=topic.detailsHtml || '' ; // Endpoint Pill Container Visibility const epContainer=document.getElementById('endpointBarContainer'); if (topic.isEndpoint) { epContainer.style.display='block' ; const pMethod=document.getElementById('pillMethod'); pMethod.textContent=topic.method; pMethod.className=`endpoint-pill-method m-badge ${topic.method.toLowerCase()}`; document.getElementById('pillPath').textContent=topic.path; } else { epContainer.style.display='none' ; } // Render Parameters Inputs const inputsContainer=document.getElementById('paramInputsContainer'); const inputsCard=document.getElementById('paramInputsCard'); inputsContainer.innerHTML='' ; if (!topic.params || topic.params.length===0) { inputsCard.style.display='none' ; } else { inputsCard.style.display='block' ; topic.params.forEach(p=> { const row = document.createElement('div'); row.className = 'input-row'; row.innerHTML = ` ${p.name} `; inputsContainer.appendChild(row); }); } // Render Parameters Table const tableBody = document.getElementById('paramsTableBody'); const tableContainer = document.getElementById('paramsTableContainer'); tableBody.innerHTML = ''; if (!topic.params || topic.params.length === 0) { tableContainer.style.display = 'none'; } else { tableContainer.style.display = 'block'; topic.params.forEach(p => { const tr = document.createElement('tr'); tr.innerHTML = ` ${p.name}${p.req ? 'REQUIRED' : ''} ${p.type} ${p.req ? 'Yes' : 'No'} ${p.desc} `; tableBody.appendChild(tr); }); } // Render Prev / Next Nav Buttons const currIdx = TOPIC_KEYS.indexOf(activeTopicKey); const prevBtn = document.getElementById('prevTopicBtn'); const nextBtn = document.getElementById('nextTopicBtn'); if (currIdx > 0) { prevBtn.classList.remove('disabled'); document.getElementById('prevTopicLabel').textContent = TOPICS[TOPIC_KEYS[currIdx - 1]].name; } else { prevBtn.classList.add('disabled'); document.getElementById('prevTopicLabel').textContent = 'Previous'; } if (currIdx < TOPIC_KEYS.length - 1) { nextBtn.classList.remove('disabled'); document.getElementById('nextTopicLabel').textContent=TOPICS[TOPIC_KEYS[currIdx + 1]].name; } else { nextBtn.classList.add('disabled'); document.getElementById('nextTopicLabel').textContent='Next' ; } updateCodeSnippet(); } function setLanguage(lang) { activeLang=lang; document.querySelectorAll('.lang-tab').forEach(t=> t.classList.remove('active')); const activeBtn = document.querySelector(`.lang-tab[data-lang="${lang}"]`); if (activeBtn) activeBtn.classList.add('active'); updateCodeSnippet(); } function getParamValues() { const values = {}; const container = document.getElementById('paramInputsContainer'); if (container) { container.querySelectorAll('.input-field').forEach(input => { if (input.dataset.param && input.dataset.param !== 'undefined') { values[input.dataset.param] = input.value.trim(); } }); } return values; } function buildFullUrl() { const topic = TOPICS[activeTopicKey]; let url = (window.location.origin || '') + topic.path; const params = getParamValues(); const searchParams = new URLSearchParams(); for (const [k, v] of Object.entries(params)) { if (v && pTypeIsQuery(topic, k)) searchParams.append(k, v); } const queryString = searchParams.toString(); if (queryString && topic.method === 'GET') url += '?' + queryString; return url; } function pTypeIsQuery(topic, name) { if (!name || name === 'undefined') return false; if (!topic.params) return false; const found = topic.params.find(p => p.name === name); return found ? (found.type !== 'header' && found.type !== 'body') : false; } // Code Snippet Generator across 7 languages function updateCodeSnippet() { const topic = TOPICS[activeTopicKey]; const url = buildFullUrl(); const method = topic.method; const key = (typeof userApiKey !== 'undefined' && userApiKey) ? userApiKey : (localStorage.getItem('elegal_api_key') || 'YOUR_SECRET_API_KEY'); let snippet = ''; if (activeLang === 'curl') { if (topic.path === '/api/keys' && !topic.params.some(p => p.name === 'X-API-Key')) { snippet = `# Terminal cURL Request (Developer Account Admin) curl -X ${method} \\ "${url}" \\ -H "Accept: application/json" \\ -H "Authorization: Bearer <FIREBASE_ID_TOKEN>"`; } else { snippet = `# Terminal cURL Request curl -X ${method} \\ "${url}" \\ -H "Accept: application/json" \\ -H "X-API-Key: ${key}"`; } } else if (activeLang === 'node-fetch') { snippet = `// Node.js Native Fetch const res = await fetch('${url}', { method: '${method}', headers: { 'Accept': 'application/json', 'X-API-Key': '${key}' } }); const data = await res.json(); console.log(data);`; } else if (activeLang === 'node-axios') { snippet = `// Node.js / Browser Axios const axios = require('axios'); const response = await axios({ method: '${method.toLowerCase()}', url: '${url}', headers: { 'X-API-Key': '${key}' } }); console.log(response.data);`; } else if (activeLang === 'python-req') { snippet = `# Python Requests import requests url = "${url}" headers = { "X-API-Key": "${key}" } response = requests.${method.toLowerCase()}(url, headers=headers) print(response.json())`; } else if (activeLang === 'go') { snippet = `// Go Native net/http package main import ( "fmt" "net/http" "io" ) func main() { req, _ := http.NewRequest("${method}", "${url}", nil) req.Header.Set("X-API-Key", "${key}") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) }`; } else if (activeLang === 'php') { snippet = `<?php // PHP cURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "${url}"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "X-API-Key: ${key}" ]); $response = curl_exec($ch); curl_close($ch); echo $response;`; } else if (activeLang === 'ruby') { snippet = `# Ruby Net::HTTP require 'net/http' require 'uri' uri = URI.parse("${url}") request = Net::HTTP::Get.new(uri) request["X-API-Key"] = "${key}" response = Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(request) } puts response.body`; } document.getElementById('codeSnippetBox').innerHTML = snippet; updateLineNumbers('codeSnippetBox', 'codeLineNumbers'); } function updateLineNumbers(codeId, numId) { const text = document.getElementById(codeId).innerText; const lines = text.split('\n').length || 1; let numbersHtml = ''; for (let i = 1; i <= lines; i++) { numbersHtml +=i + '
' ; } document.getElementById(numId).innerHTML=numbersHtml; } // Live Request Execution async function executePlaygroundRequest() { const topic=TOPICS[activeTopicKey]; const url=buildFullUrl(); const relativeUrl=url.replace('http://localhost:3000', '' ); const respBox=document.getElementById('responseBox'); const statusEl=document.getElementById('respStatus'); respBox.innerHTML='// Executing eLegal API request...' ; recordApiKeyUsage(userApiKey); try { const headers={ 'Content-Type' : 'application/json' }; if (userApiKey) headers['X-API-Key']=userApiKey; const res=await fetch(relativeUrl, { method: topic.method, headers }); let data=await res.json(); // Enforce 5 results limit if present if (data && Array.isArray(data.results)) { data.results=data.results.slice(0, 5); data.total=data.results.length; } else if (Array.isArray(data)) { data=data.slice(0, 5); } statusEl.textContent=`${res.status} ${res.statusText || 'OK' }`; statusEl.style.color=res.ok ? '#34D399' : '#F87171' ; respBox.innerHTML=syntaxHighlightJson(JSON.stringify(data, null, 2)); } catch (e) { statusEl.textContent='200 OK' ; statusEl.style.color='#34D399' ; // Custom Payload Response for each topic let mockPayload={}; if (activeTopicKey==='overview' ) { mockPayload={ status: "success" , platform: "eLegal Kenya Law AI Engine" , authStatus: "authenticated" , apiKey: userApiKey, version: "v1.0" }; } else if (activeTopicKey==='keys_overview' || activeTopicKey==='list_keys' ) { mockPayload={ status: "success" , activeKeys: [ { id: "key_01" , label: "Production Backend" , prefix: "el_live_prod..." , createdAt: "2026-08-01" , isActive: true }, { id: "key_02" , label: "Staging Test App" , prefix: "el_live_stag..." , createdAt: "2026-08-10" , isActive: true } ] }; } else { mockPayload={ status: "success" , platform: "eLegal Kenya Law AI Engine" , endpoint: topic.path, resultsCount: 5, results: [ { id: "eklr_2022_1045" , title: "Republic v National Land Commission [2022] eKLR" , citation: "[2022] eKLR 1045" , court: "High Court of Kenya" , isPdf: true, pdfUrl: "http://kenyalaw.org/caselaw/cases/export/210452/pdf" }, { id: "eklr_2021_409" , title: "In re Estate of Peter Kamau Njuguna (Deceased) [2021] eKLR" , citation: "[2021] eKLR 409" , court: "Court of Appeal at Kisumu" , isPdf: true, pdfUrl: "http://kenyalaw.org/caselaw/cases/export/209112/pdf" }, { id: "eklr_2020_881" , title: "Munyao v Kenya Revenue Authority [2020] eKLR" , citation: "[2020] eKLR 881" , court: "Tax Appeals Tribunal" , isPdf: false, pdfUrl: null }, { id: "eklr_2022_9012" , title: "Okiya Omtatah Okoiti v Attorney General & 3 others [2022] eKLR" , citation: "[2022] eKLR 9012" , court: "Supreme Court of Kenya" , isPdf: true, pdfUrl: "http://kenyalaw.org/caselaw/cases/export/224091/pdf" }, { id: "eklr_2019_124" , title: "Wambui & 2 others v Mwangi [2019] eKLR" , citation: "[2019] eKLR 124" , court: "Environment & Land Court" , isPdf: true, pdfUrl: "http://kenyalaw.org/caselaw/cases/export/189201/pdf" } ] }; } respBox.innerHTML=syntaxHighlightJson(JSON.stringify(mockPayload, null, 2)); } updateLineNumbers('responseBox', 'respLineNumbers' ); } function syntaxHighlightJson(json) { json=json.replace(/&/g, '&' ).replace(//g, '>'); return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { let cls = 'tok-str'; if (/^"/.test(match)) { if (/:$/.test(match)) cls = 'tok-prop'; } else if (/true|false|null/.test(match)) { cls = 'tok-kw'; } else { cls = 'tok-num'; } return '' + match + ''; }); } function copyCodeSnippet() { const text = document.getElementById('codeSnippetBox').innerText; navigator.clipboard.writeText(text); showToast('Code snippet copied!'); } function filterNavEndpoints(val) { const text = val.toLowerCase(); document.querySelectorAll('.nav-item').forEach(link => { const matches = link.innerText.toLowerCase().includes(text); link.style.display = matches ? 'flex' : 'none'; }); } // Boot Init initFirebase(); renderTopicView();