Skip to main content
TrackJud TrackJud
· Updated on · 6 min read

Brazilian court data API: how to automate lawsuit research across 10 states

By TrackJud

Integrate the Vigilant REST API to query Brazilian court cases. Endpoints, auth, cache behavior, RFC 7807 errors, and examples in cURL, Python, JavaScript. Updated April 2026.

TL;DR: Vigilant’s REST API unifies access to 12 Brazilian judicial sources (ESAJ + PJe) behind a single OpenAPI 3.1 interface. Bearer token auth, standardized JSON responses, RFC 7807 errors. Smart 2-day cache (200 if fresh, 202 + polling if new). 6 endpoints: health, courts, create/get/cancel/reprocess consult. Cost: R$ 0.10 per court queried. Minimum integration: 2-4 hours. Postman collection available.

If you are a developer at a legaltech, fintech, compliance platform, or international audit firm and you need to automate lawsuit research across Brazilian courts, this guide is for you.

The problem

Brazilian courts do not offer official APIs for lawsuit consultation. Each court runs its own system (ESAJ, PJE, and others), with different interfaces and data formats. Compounding the problem: there is no English-language documentation for any of these systems, and error messages are all in Portuguese.

For anyone who needs Brazilian court data at scale or integrated into an external system, the options are:

  1. Manual consultation — does not scale
  2. Build and maintain your own integration — high engineering cost, constant maintenance, requires Portuguese-speaking ops
  3. Use an API that already solves this — focus on your product

Vigilant is the third option: a REST API that unifies access to 12 court sources across 10 Brazilian states.

API overview

AspectDetail
ProtocolREST + JSON
AuthenticationBearer token (API key)
DocumentationOpenAPI 3.1 with interactive Scalar UI (English + Portuguese)
Base URLhttps://vigilant.trackjud.com.br/api/v1
ErrorsRFC 7807 Problem Details

Getting started

1. Create an account

Go to vigilant.trackjud.com.br and create an account with email. You get 5 free credits immediately.

2. Generate an API key

In the dashboard, go to API Keys > Create new key. The key is displayed only once — copy and store it securely.

3. Authentication

All calls use Bearer tokens:

Authorization: Bearer vgl_your_key_here

Endpoints

List available courts

GET /api/v1/courts

Returns all courts with their operational status (active, unavailable, coming_soon). Use this to know which courts can be searched.

Create a consult

POST /api/v1/consults
{
  "document": "529.982.247-25",
  "courts": ["TJSP", "TJMG", "TJPE"]
}
FieldTypeRequiredDescription
documentstringYesCPF (Brazilian individual ID — 11 digits, with or without mask)
courtsarrayYesCourt codes
force_refreshbooleanNoGuaranteed-fresh data (5x cost)

Responses:

  • 200 — data available (cache). Lawsuits returned immediately.
  • 202 — search started. Use consult_id to poll for results.
  • 402 — insufficient credits.
  • 422 — invalid CPF or unsupported court.

Get results

GET /api/v1/consults/{consult_id}

Poll until status is done. Each court within the consult has its own status.

Cancel a consult

DELETE /api/v1/consults/{consult_id}

Reprocess failed courts

POST /api/v1/consults/{consult_id}/reprocess

Reprocesses only courts that failed. Charges credits proportionally.

Response data

For each lawsuit found:

{
  "numero_processo_unico": "1234567-89.2024.8.26.0100",
  "classe": "Procedimento Comum Cível",
  "situacao": "Em andamento",
  "distribuido_em": "15/01/2024",
  "valor_causa": "R$ 50.000,00",
  "instance": "1",
  "partes": [
    { "tipo": "Autor", "nome": "João da Silva", "representante": "Dr. Lawyer OAB/SP 12345" },
    { "tipo": "Réu", "nome": "Empresa XYZ Ltda" }
  ],
  "movimentos": [
    { "data_movimento": "01/03/2024", "descricao": "Petition filing" }
  ],
  "assuntos": [
    { "cod_assunto": 7619, "ds_assunto": "Moral damages" }
  ]
}

Note on field names: the response preserves the original Portuguese field names from Brazilian court systems (numero_processo_unico, classe, partes, etc.) because these are domain terms defined by the CNJ (Brazil’s judicial council). This makes it easier to cross-reference with official Brazilian documentation.

The format is standardized regardless of which court the data came from.

Practical examples

curl

# Create a consult
curl -X POST https://vigilant.trackjud.com.br/api/v1/consults \
  -H "Authorization: Bearer vgl_your_key" \
  -H "Content-Type: application/json" \
  -d '{"document":"529.982.247-25","courts":["TJSP","TJMG"]}'

# Get results
curl https://vigilant.trackjud.com.br/api/v1/consults/CONSULT_ID \
  -H "Authorization: Bearer vgl_your_key"

Python

import requests
import time

API_URL = "https://vigilant.trackjud.com.br/api/v1"
headers = {"Authorization": "Bearer vgl_your_key"}

# Create a consult
resp = requests.post(f"{API_URL}/consults", headers=headers, json={
    "document": "529.982.247-25",
    "courts": ["TJSP", "TJMG", "TJPE"]
})

data = resp.json()["data"]
consult_id = data["consult_id"]

# Cache hit (200) — data already available
if resp.status_code == 200:
    for court in data["courts"]:
        print(f"{court['court']}: {len(court['processes'])} lawsuits")
else:
    # Polling (202) — wait for processing
    while True:
        time.sleep(5)
        resp = requests.get(f"{API_URL}/consults/{consult_id}", headers=headers)
        result = resp.json()["data"]
        if result["status"] == "done":
            for court in result["courts"]:
                print(f"{court['court']}: {len(court.get('processes', []))} lawsuits")
            break

JavaScript

const API_URL = "https://vigilant.trackjud.com.br/api/v1";
const headers = {
  "Authorization": "Bearer vgl_your_key",
  "Content-Type": "application/json"
};

// Create a consult
const resp = await fetch(`${API_URL}/consults`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    document: "529.982.247-25",
    courts: ["TJSP", "TJMG"]
  })
});

const { data } = await resp.json();

// Poll if needed
if (resp.status === 202) {
  const poll = async () => {
    const r = await fetch(`${API_URL}/consults/${data.consult_id}`, { headers });
    const result = await r.json();
    if (result.data.status === "done") return result.data;
    await new Promise(r => setTimeout(r, 5000));
    return poll();
  };
  const result = await poll();
  console.log(JSON.stringify(result, null, 2));
}

Error handling

All errors follow the RFC 7807 Problem Details standard:

{
  "type": "https://vigilant.trackjud.com.br/errors/validation-error",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "The request contains invalid fields",
  "errors": {
    "document": ["has invalid format"]
  }
}
StatusWhen
400Unknown court or empty list
401Missing or invalid API key
402Insufficient credits
404Consult not found
409Conflict (e.g., canceling an already-finished consult)
422Invalid CPF

Interactive documentation

Full API documentation is available with interactive examples:

The OpenAPI 3.1 spec can be imported into Postman, Insomnia, or any compatible tool.

Pricing

PackCreditsPricePer credit
Starter100R$ 10 (~US$ 2)R$ 0.10
Professional500R$ 45R$ 0.09
Business2,000R$ 160R$ 0.08
Enterprise10,000R$ 700R$ 0.07

1 credit = 1 court searched. No subscription. Credits never expire. Pricing is in Brazilian Reais (BRL) — the product is billed in BRL regardless of where the customer is located.


5 free credits to try. Create your account.

Frequently asked questions

Is there an official SDK for Python, Node.js, or Go?

Not yet. The API is pure REST + JSON, documented in OpenAPI 3.1. Any HTTP client works: requests (Python), fetch/axios (Node), net/http (Go). The OpenAPI spec is at vigilant.trackjud.com.br/api/openapi — generate a client automatically with openapi-generator or oapi-codegen if you want. To test calls before coding, download our Postman collection with all 6 endpoints pre-configured.

Is there a sandbox environment?

No separate sandbox. New accounts get 5 free credits that work as a sandbox — same production URL, same API key, same real responses. No fake environment with simulated data. What works in testing works in production with zero config changes.

What's the rate limit?

Free accounts have per-key rate limits sufficient for development (~60 requests/min). Enterprise contracts negotiate dedicated rate limits and bursting. When the limit is hit, the API returns HTTP 429 with a Retry-After header. In practice, rate limits are irrelevant for most use cases because the API is async — you create a consult (1 request), then poll (1 request every 2-5s).

Does the API return real-time data or cached data?

Depends. 3 scenarios: (1) Fresh cache (<2 days): HTTP 200 with stored data, source='cache'. (2) Stale cache (≥2 days): HTTP 200 with old data + stale=true + background refresh. (3) No cache: HTTP 202, consult created, poll the consult_id until status='done'. force_refresh=true bypasses cache entirely (5x cost).

How does error handling work?

All error responses follow RFC 7807 (Problem Details) with Content-Type application/problem+json. Standard fields: type (error URI), title (human-readable), status (HTTP code), detail (specific explanation), instance (request path). Validation errors (422) include an extra errors field with per-field details. Most common codes: 400 (unknown court), 401 (invalid key), 402 (insufficient credits), 404 (consult not found), 422 (invalid CPF), 429 (rate limit).

How long does integration take?

Depends on scope. Minimum integration (call API + display result): 2-4 hours for a dev who knows REST. Integration with monitoring (polling + diff + alerts): 1-2 days. Full integration into a decision engine (webhook + normalized judicial score): 1-2 weeks.

Can I query by CNPJ (company ID)?

Yes. The document field accepts both CPF (11 digits) and CNPJ (14 digits), masked or unmasked. For CNPJ, the API returns cases where the company is a party (plaintiff or defendant), including labor claims — useful for supplier auditing.

What happens if a court is down?

The API has automatic retry (up to 3 attempts by default). If the court stays down after retries, that specific court_search gets status 'unavailable' and the credit is refunded automatically. You can call /reprocess later to retry only the failed courts. The consult_id is preserved.

Related articles