Integration reference
Start here
- Verify your attorney account in the API console. Your API membership must be active.
- Open Overview to compare permitted incidents and unlocked details. A webhook is not needed to view these records.
- Open Connection and create a key with the permissions your application needs. Store it in your application's secret manager.
- Use the Postman collection or the HTTPS examples below. To test delivery without firm software, create the Lukhoo test receiver and inspect Activity.
- Register your firm's HTTPS endpoint, store its signing secret, and send a test. Live events start only after the endpoint returns a successful response to a test.
Read permitted records
Base URL: https://lukhoo.com/api/attorney/v1. Send Authorization: Bearer YOUR_API_KEY. Keys identify the attorney; never send an attorney ID to select an account.
curl -sS https://lukhoo.com/api/attorney/v1/incidents \ -H "Authorization: Bearer $LUKHOO_API_KEY"
An incident has access: "summary" until its permitted contact window is open. An active API membership is required for details. Evidence downloads also require the client's current sharing permission.
Use GET /incidents/{videoId}/artifacts/video, /transcript, or /legal_brief for authorized file streams. Storage configuration must be completed by Lukhoo first.
Contact, message, confirm
- Open contact with
POST /incidents/{videoId}/contactand an empty JSON object. Use only a designated test client when testing. This starts a contact window and notifies the client. - Use the returned
conversation_idto read and send messages at/conversations/{id}/messages. - Send
{"confirm":true}toPOST /conversations/{id}/hire-confirmationwhen the attorney agrees to represent the client. This records only the attorney's confirmation. - The client confirms on their existing Lukhoo page. The hire is complete when both confirmations are present. Messaging can continue after the hire.
POST /conversations/123/messages
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: UNIQUE-REQUEST-REFERENCE
{"body":"Your message to the client, up to 524 characters."}
Messages, notifications and checkpoints use the same records as the portal. Use POST /conversations/{id}/read with {"through_id":"456"} to mark received messages read.
Reuse an Idempotency-Key and the exact same body when retrying an uncertain contact, message, or confirmation request. A new action needs a new key. A reused key with a different body returns 409.
Receive changes
Events are detected by polling the shared sources, normally every 10 seconds plus processing and source latency. Multiple rapid incident edits can become one current-state update. This is near-real-time delivery, not a promise to capture every intermediate database write.
Supported events: incident.created, incident.updated, incident.removed, conversation.updated, message.created, and message.updated. Score or evidence changes appear as incident.updated.
{
"spec_version": "1.0",
"event_id": "b38d0a60-2367-4c67-a6ad-bb9d83243a12",
"sequence": "125",
"event_type": "incident.updated",
"created_at": "2026-09-08T18:00:00.000Z",
"data": {
"resource_type": "incident",
"resource_id": "100001",
"resource_url": "/api/attorney/v1/incidents/100001"
}
}
Webhooks carry references. Fetch the resource with your key to receive the currently permitted details. Treat incident.removed as an instruction to stop displaying the record. When a fetch returns 403 or 404, remove cached details from your active view.
For two-way messaging in firm software, receive message.created, fetch its resource_url, read the returned conversation_id, and reply with POST /conversations/{conversation_id}/messages. The client's message and the attorney's API reply use the same Lukhoo conversation, notification, and checkpoint records as the portal.
Verify Lukhoo-Signature before parsing the JSON. It contains t=UNIX_SECONDS,v1=HEX_DIGEST. Calculate HMAC-SHA256 using the signing secret and the exact bytes of timestamp + "." + raw_request_body. Compare using a timing-safe comparison and reject timestamps more than five minutes away from your server clock.
Persist the event before returning a 2xx response. Deduplicate by event_id; retries can arrive more than once or out of order. The delivery ID stays the same across retries. Failed delivery is retried up to eight attempts with delays capped at one hour, then appears as failed for manual retry.
Use GET /events?after=125&limit=100 to resume from a saved event sequence. The incidents list uses an offset, so rescan incidents from zero when reconciling a changed list.
Access and operations
API-only membership permits API use. Portal-only membership does not permit API use. A bundle permits both. Trial duration and billing are managed by the existing Stripe configuration.
Manage cancellation through Manage Billing in the menu. Access ends when the existing membership service reports the subscription inactive; a cancellation scheduled for the end of a billing period remains active until that time. No further details or event delivery are provided after access is inactive. Information already downloaded cannot be remotely recalled.
Keys can be rotated or revoked in Connection. Rotation invalidates the old key immediately. Webhook endpoints can be paused at any time. To replace a signing secret or change an endpoint, register and test its replacement, then pause the old endpoint.
Activity shows delivery results and per-route usage. Delivery success is delivered jobs divided by delivered plus permanently failed jobs; pending and suppressed jobs are excluded. Counters use the current UTC calendar month.
Requests are limited to 300 per minute per source IP and 600 per minute per attorney account. Honor 429 and the rate-limit headers. A 503 means a required service could not be verified; retry with backoff.
JSON is the supported wire format. OpenAPI describes the contract, and the Postman collection provides ready-to-run requests. File downloads keep their native MP4, TXT and PDF formats.