HTTP API

Pelaikan API Documentation

Use the API to extract citations from a PDF, resolve each citation to a source, and analyze whether the source supports the proposition in the document. This page summarizes the main endpoints used by the hosted Firebase web app and by external API clients.

Basics

The production API base is currently:

https://pelaikan-api-772587166095.europe-west9.run.app

Firebase Hosting also rewrites /api/** to the Cloud Run service, so website calls can use same-origin paths such as /api/web/audit/resolve.

Authentication

Every main endpoint requires an access token:

Authorization: Bearer <access_token>

The walkthrough token is a short-lived HS256 JWT with issuer footcheck, audience footcheck-api, a subject user id, a client id, and roles such as api or user.

For API access with a bearer token, email pelekandc@gmail.com.

Common Fields

  • document_id: stable id used for OCR, parsing, resolution, and result caches.
  • data_source: usually internet. folder is for desktop bridge clients with a local database.
  • internet_policy: off, smart, or on. Hosted /web/* resolution behaves as on.
  • client_id: normally read from the token; only pass it for bridge-style desktop operations.

Health and Identity

GET
/version

Returns the backend version payload. This endpoint is useful for smoke checks and does not use the full workflow body.

GET
/session/whoami

Returns token claims such as sub, cid, and roles. Use it to verify that the bearer token is accepted before running expensive steps.

One Go Endpoint

Use POST /v1/verify_pdf when you want the server to run OCR, parse citations, resolve sources, and analyze congruence in one request. The response is a Server-Sent Events stream, so clients receive progress and result rows as work completes.

POST
/v1/verify_pdf
Inputmultipart/form-data with required file PDF, required document_id, and optional config as JSON text.
Outputtext/event-stream. Events are start, progress, row, complete, and error.
AuthRequires Authorization: Bearer <access_token>. The token subject is used for document registration, OCR cache, and credit checks. To request a bearer token, email pelekandc@gmail.com.

Config

The config form field is JSON. You can also fetch the live schema from GET /v1/verify_pdf/config-schema.

FieldDefaultMeaning
allowed_kindsnullSource kinds to verify, for example ["precedent","legal_norm"]. null verifies all kinds.
skip_cross_referencestrueSkip references like ibid. or see supra.
require_claimtrueSkip citations without an extracted claim.
skip_dryfalseSkip bare/dry citations if set to true.
include_footnotestrueParse and verify footnote citations.
include_inlinetrueParse and verify inline citations from page body text.
inline_pagesnullOptional 1-based page numbers to parse inline. null means all pages.
congruence_methodmicro_tasksmicro_tasks or standard.
internet_policysmartoff, smart, or on.
concurrency4Internal parallelism, clamped server-side to the endpoint cap.
max_footnotesnullOptional cost-control cap on parsed footnotes.
max_inlinenullOptional cost-control cap on inline citations.
force_ocrfalseForce OCR even if a cached result exists.

cURL

curl -N -X POST "$API_BASE/v1/verify_pdf" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -F "file=@brief.pdf;type=application/pdf" \
  -F "document_id=brief-2026-06-05" \
  -F 'config={
    "allowed_kinds": ["precedent", "legal_norm"],
    "include_footnotes": true,
    "include_inline": true,
    "inline_pages": [1, 2, 3],
    "max_footnotes": 20,
    "max_inline": 30,
    "concurrency": 4
  }'

JavaScript

async function verifyPdf({ apiBase, accessToken, file, documentId }) {
  const form = new FormData();
  form.append("file", file);
  form.append("document_id", documentId);
  form.append("config", JSON.stringify({
    allowed_kinds: ["precedent", "legal_norm"],
    include_footnotes: true,
    include_inline: true,
    require_claim: true,
    concurrency: 4,
  }));

  const response = await fetch(`${apiBase}/v1/verify_pdf`, {
    method: "POST",
    headers: { Authorization: `Bearer ${accessToken}` },
    body: form,
  });

  const reader = response.body
    .pipeThrough(new TextDecoderStream())
    .getReader();

  let buffer = "";
  const rows = [];
  let summary = null;

  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    buffer += value;

    const chunks = buffer.split("\n\n");
    buffer = chunks.pop() || "";

    for (const chunk of chunks) {
      const event = chunk.match(/^event: (.+)$/m)?.[1];
      const dataLine = chunk.match(/^data: (.+)$/m)?.[1];
      if (!event || !dataLine) continue;
      const data = JSON.parse(dataLine);

      if (event === "row") rows.push(data);
      if (event === "complete") summary = data.summary;
      if (event === "error") throw new Error(data.detail || data.error);
    }
  }

  return { rows, summary };
}

Stream Events

EventPayload
startdocument_id, page count, footnote count, ocr_cached, elapsed seconds.
progressstage, completed, and total. Stages include parse_footnotes, parse_inline, and resolve_analyze.
rowOne verified citation row with kind, footnote_id, page_number, cite_id, cite_raw, source_kind, claim, resolution fields, congruence_label, calibration, quote_label, and truncated rationale.
completeAll rows, plus summary.total, summary.by_label, and elapsed seconds.
errorerror and optional detail. Insufficient credit is reported here when the initial balance check fails.

This endpoint is synchronous from the client's point of view, but it streams progress to avoid holding a silent long-running request. Keep the HTTP connection open until the complete event arrives.