Search¶
Search official government registries for a company. Searches are asynchronous: you submit a request, receive a searchId (and caseId), then poll until the work finishes.
A successful root search creates a new case and sets case.target to the found entity. To dig into a counterparty already on a case (ownership tree), use Expand search instead.
Submit a company search¶
Request¶
Headers
| Header | Value |
|---|---|
Content-Type |
application/json |
X-API-Key or Authorization |
rev_… or Bearer <idToken> |
Body
| Field | Type | Required | Description |
|---|---|---|---|
identifier |
string | Conditional | Registry registration number / search id. Required for most jurisdictions. |
legal_name |
string | Conditional | Legal name. Required (instead of or in addition to identifier) for name-based jurisdictions (e.g. ID, MX, IQ, and others whose coverage schema lists legal_name without a required identifier). |
jurisdiction |
string | Yes | Jurisdiction code (e.g. GB, DE, US-DE, CH-ZH). |
include |
object | No | Optional add-ons |
include.financials |
boolean | No | Request financial metrics when the jurisdiction supports them. Extra credits only if financials data is returned. |
Info
At least one of identifier or legal_name is required, depending on the jurisdiction’s search schema. If both are missing, or only a name is sent for an identifier-only jurisdiction, the API returns 400.
Immediate response (200)¶
A search record with status: "PENDING":
{
"_id": "abc123searchId",
"caseId": "xyz789caseId",
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:00.000Z",
"userId": "user-uid",
"searchInputs": {
"identifier": "HRB 246975",
"jurisdiction": "DE",
"include": { "financials": true }
},
"status": "PENDING"
}
| Field | Type | Description |
|---|---|---|
_id |
string | Search ID. Use this to poll status. |
caseId |
string | New case grouping this search (and later expands / LEI lookups) |
status |
string | PENDING, COMPLETED, or FAILED |
searchInputs |
object | Echo of accepted search parameters |
userId |
string | Owner uid |
createdAt / updatedAt |
string | ISO 8601 timestamps |
Work continues in the background. Poll Get search status.
Error responses¶
Credits¶
- The jurisdiction search cost is debited up front when the search is accepted.
- On scrape / processing failure, that cost is refunded.
include.financials: charged after success only if numeric financials came back. A charge failure is logged and does not roll back the search.
You must be subscribed to the jurisdiction and have enough volume_remaining.
Get search status / results¶
Request¶
Headers
| Header | Value |
|---|---|
X-API-Key or Authorization |
API key or Bearer token |
Path parameters
| Parameter | Type | Description |
|---|---|---|
searchId |
string | _id from the POST response |
Response¶
{
"_id": "abc123searchId",
"caseId": "xyz789caseId",
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:05.000Z",
"userId": "user-uid",
"searchInputs": {
"identifier": "HRB 246975",
"jurisdiction": "DE"
},
"status": "COMPLETED",
"result": {
"_id": "entity-uuid",
"legalName": "EXAMPLE GMBH",
"legalForm": "Gesellschaft mit beschränkter Haftung",
"companyStatus": "Active",
"countryOfRegistration": "DE",
"jurisdiction": "DE",
"registrationDate": "2020-03-15",
"addresses": [],
"identifiers": [],
"relationships": [],
"activities": [],
"capital": {},
"otherNames": [],
"counterparties": [],
"sourceDocuments": []
}
}
result is a full Entity. On some jurisdictions (e.g. Singapore async document fulfilment) the search may stay PENDING with pendingDocument: true while a paid filing is still generating.
{
"_id": "abc123searchId",
"caseId": "xyz789caseId",
"status": "FAILED",
"result": {
"error": "Timeout while fetching registry data"
},
"searchInputs": {
"identifier": "HRB 246975",
"jurisdiction": "DE"
},
"createdAt": "2026-01-15T10:30:00.000Z",
"updatedAt": "2026-01-15T10:30:30.000Z",
"userId": "user-uid"
}
Polling strategy¶
- Wait ~2 seconds after submit.
GET /search/{searchId}/status.- If
PENDING, wait 3 seconds and poll again. - Increase the interval up to ~10 seconds.
- Stop on
COMPLETEDorFAILED.
Average registry times vary widely (seconds to a few minutes). See Data Coverage.
Example (cURL)¶
RESPONSE=$(curl -sS -X POST https://api.revolutio.systems/search \
-H "Content-Type: application/json" \
-H "X-API-Key: $REV_API_KEY" \
-d '{"identifier": "09215191", "jurisdiction": "GB"}')
SEARCH_ID=$(echo "$RESPONSE" | jq -r '._id')
CASE_ID=$(echo "$RESPONSE" | jq -r '.caseId')
sleep 3
curl -sS "https://api.revolutio.systems/search/$SEARCH_ID/status" \
-H "X-API-Key: $REV_API_KEY" | jq .
Expand search¶
Follow-on registry search on a counterparty already on a case.
Unlike POST /search (new case, overwrites case.target), expand grafts the new ownership layer under the chosen company node.
The request is async: HTTP returns as soon as a PENDING search is saved.
Endpoint¶
Same function as company search. Related paths:
| Method | Path | Purpose |
|---|---|---|
POST |
/search/expand |
Start expand |
GET |
/search/{searchId}/status |
Full search doc (incl. result when done) |
GET |
/casefile/{caseId} |
Case + search summaries (no nested result) |
Request body¶
{
"caseId": "abc123",
"parentEntityId": "entity-uuid-on-case",
"jurisdiction": "DE",
"identifier": "HRB 12345",
"legalName": "Example GmbH",
"include": {
"financials": true
}
}
| Field | Required | Notes |
|---|---|---|
caseId |
Yes | Existing case id |
parentEntityId |
Yes | _id of the target or a counterparty on that case |
jurisdiction |
No | Defaults from the entity (jurisdiction / countryOfRegistration) |
identifier |
No* | Registry registration number. Defaults from the entity’s identifiers |
legalName |
No | Defaults from the entity |
include.financials |
No | Same opt-in as POST /search |
* A registration number is required. If neither the body nor the entity has one, the API responds 400 and tells you to resolve it first via IDFinder. Expand does not auto-pick a registry id (wrong match would corrupt the ownership graph).
Minimal example¶
curl -sS -X POST "https://api.revolutio.systems/search/expand" \
-H "Content-Type: application/json" \
-H "X-API-Key: $REV_API_KEY" \
-d '{
"caseId": "CASE_ID",
"parentEntityId": "PARENT_ENTITY_ID"
}'
Immediate response (200)¶
{
"_id": "SEARCH_ID",
"caseId": "CASE_ID",
"createdAt": "2026-…",
"updatedAt": "2026-…",
"userId": "UID",
"searchType": "expand",
"parentEntityId": "PARENT_ENTITY_ID",
"searchInputs": {
"identifier": "…",
"jurisdiction": "DE",
"legalName": "…"
},
"status": "PENDING"
}
Poll GET /search/{searchId}/status until COMPLETED or FAILED. On success, new counterparties are merged onto the case under parentEntityId.
Expand credits¶
- Base jurisdiction cost debited up front (same as
POST /search). - On failure, base cost is refunded.
- Financials charged after success only if data returns.
Expand errors¶
| Status | When |
|---|---|
400 |
Missing caseId / parentEntityId; unsupported jurisdiction; no registration number |
401 |
Missing or invalid auth |
402 |
Insufficient credits |
403 |
Not case owner; account locked; not subscribed to jurisdiction |
404 |
Case not found; entity not on case; user profile missing |
409 |
Counterparty already expanded, or an expand for that entity is already PENDING |
429 |
Rate limit |
500 |
Internal error (credits refunded if already charged) |
Example when the entity has no registry number:
{
"error": "No registration number for this company. Resolve it first via /idfinder.",
"legalName": "Example GmbH",
"jurisdiction": "DE"
}
Expand behaviour notes¶
- Idempotent per entity: once something in the case already points at
parentEntityIdas a parent, further expands return409. - One in-flight expand per
parentEntityId(PENDINGblocks a second start). - Expand does not create a new case; it mutates the existing case graph under the expanded node.
- Only the case owner may expand (collaborator access is not enough).
- Prefer re-fetching the case for UI structure; use search status for the full expand
resultand failure details.
Typical end-to-end flow¶
1. POST /search → caseId + root company
2. (optional) POST /idfinder → registry number for a counterparty without one
3. POST /search/expand → caseId + parentEntityId (+ identifier if needed)
4. GET /search/{id}/status → wait for COMPLETED | FAILED
5. GET /casefile/{caseId} → updated ownership tree (summaries + target graph)