LLegiScoreSearch API
Get an API key
Get started
IntroductionAuthenticationQuickstartSearch lifecycleErrorsWebhooksCreditsGet an API key
API reference
Credit balancegetCataloggetLookupsgetSearchespost
States
All states
View as Markdownllms-full.txt

Get started

Webhooks

Skip polling. Give a callback_url and we POST the finished search to you, signed so you can prove it came from LegiScore.

Turn it on

Add callback_url to a search, or once at the top of a batch. It must be https and carry no username or password. Without one, the webhook subscriptions configured on your workspace receive the same events.

Events

EventSent when
search.completedA search reaches succeeded.
search.failedA search reaches failed or cancelled.
request body
{
  "delivery_id": "dlv_7f3a...",
  "event": "search.completed",
  "api_version": "2026-04-26",
  "occurred_at": "2026-10-05T10:03:12Z",
  "data": {
    "search": { "id": "SRCH-2026-A1B2C3D4", "status": "succeeded", "found": true, "...": "..." },
    "links": {
      "self": "/api/v1/search/SRCH-2026-A1B2C3D4",
      "documents": ["/api/v1/search/SRCH-2026-A1B2C3D4/documents/result.pdf"]
    }
  }
}

Links are paths, not signed URLs. Call them with your API key to download documents.

Verify the signature

HeaderValue
X-LegiScore-EventThe event name.
X-LegiScore-DeliveryUnique id for this delivery. Use it to de-duplicate.
X-LegiScore-TimestampUnix time the delivery was signed.
X-LegiScore-Signaturesha256= plus the hex HMAC-SHA256 of "<timestamp>.<raw body>", keyed with your webhook secret.
import crypto from "node:crypto";

export function verify(rawBody, headers, secret) {
  const timestamp = headers["x-legiscore-timestamp"];
  const received = headers["x-legiscore-signature"]; // "sha256=<hex>"
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  const a = Buffer.from(received);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
import hashlib
import hmac


def verify(raw_body: bytes, headers: dict, secret: str) -> bool:
    timestamp = headers["X-LegiScore-Timestamp"]
    received = headers["X-LegiScore-Signature"]  # "sha256=<hex>"
    signed = timestamp.encode() + b"." + raw_body
    expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(received, expected)
Verify against the raw body
Compute the HMAC over the exact bytes received, before any JSON parsing. Reject deliveries whose timestamp is more than a few minutes old.

Delivery and retries

  • Answer with any 2xx within 30 seconds to acknowledge.
  • Anything else, or a timeout, is retried: after 60, 120, 240, 480 and 960 seconds (6 attempts in all).
  • The same delivery can arrive twice. De-duplicate on X-LegiScore-Delivery.
  • Webhooks are a convenience. Polling GET /api/v1/search/{id} always gives the truth.
PreviousErrorsNextCredits