UNICORN PRIVATE Intelligence

Unicorn Intelligence API

REST API over HTTPS with JSON bodies, for every plan. The OpenAPI 3.1 specification is at /openapi.json. Information tool: decisions and legal obligations remain with the customer; every item carries its source and date.

Authentication · Plans and limits · Errors · Screening · Dossiers · Monitoring · Webhooks · Examples

Authentication

An admin creates keys in the dashboard (API tab). Keys start with ui_live_, are shown once and are stored only as a SHA-256 hash. Several named keys can be active; revoke them individually.

curl https://intel.unicornprivate.com/v1/usage -H "Authorization: Bearer ui_live_..."

Plans and limits

Each endpoint works only if the service is in your plan (otherwise 403 plan_upgrade_required). Limits are applied automatically: names monitored (100, 1,000 or 10,000), dossiers per month (plus purchased single dossiers), countries or areas for regulatory monitoring, competitors and sectors, tender search profiles. GET /v1/usage returns modules, limits and usage. Rate limit: 600 requests per minute per account (429 too_many_requests).

Plans are bought on the pricing page or in the dashboard. Monthly: card only, renews automatically, cancel whenever you want. Annual: 10 months paid for 12, by card or by bank transfer (bank transfer only for annual plans). GET /v1/usage returns the plan ids below.

Plan idIncludesMonthYear
screening_100Screening Base: Sanctions and counterparty screening, up to 100 names.$1,500$15,000
screening_1kScreening Business: Sanctions and counterparty screening, up to 1,000 names.$2,500$25,000
screening_10kScreening Enterprise: Sanctions and counterparty screening, up to 10,000 names.$4,000$40,000
dossier_10Dossier 10: Dossiers on private companies, 10 per month.$3,900$39,000
sectorSector: Competitor and startup intelligence, 10 competitors and 3 sectors.$2,000$20,000
regulation_3Regulation 3: Regulatory monitoring, 3 countries or areas.$1,500$15,000
regulation_10Regulation 10: Regulatory monitoring, 10 countries or areas.$3,500$35,000
tendersTenders: International public tenders, all portals, 5 search profiles.$900$9,000
sanctionsSanctions and third parties: Screening Base (100 names) and 5 dossiers per month. Services bought separately: $3,950/month.$2,400$24,000
complianceCompliance: Screening Base (100 names), Regulation 3 countries and 5 dossiers per month. Services bought separately: $5,450/month.$3,900$39,000
growthMarket and growth: Sector, Tenders and Regulation 3 countries. Services bought separately: $4,400/month.$3,400$34,000
completeComplete: Screening Enterprise (10,000 names), Regulation 10 countries, Sector, Tenders and 10 dossiers per month. Services bought separately: $14,300/month.$9,900$99,000

Errors

Errors use HTTP status codes and a JSON body:

{"error": {"code": "limit_exceeded", "message": "Your plan includes up to 1,000 names; you have 990.", "status": 403, "docs": "https://intel.unicornprivate.com/docs#errors"}}
StatusCodes
400invalid_json, invalid_parameter, invalid_entity, invalid_url
401invalid_api_key
402subscription_inactive, dossier_quota_exceeded
403plan_upgrade_required, limit_exceeded
404not_found
413payload_too_large, too_many_entities
429too_many_requests
502, 503engine_error, module_unavailable (retry later; see /status)

Screening

Names are compared every day with the lists shown on /status. Upsert by your own ref:

POST /v1/entities
{"entities": [{"ref": "SUP-0042", "name": "Example Trading LLC", "type": "company", "country": "AE", "aliases": ["Example Trading"]},
              {"ref": "DIR-7", "name": "Jane Example", "type": "person", "dob": "1970-05"}]}
-> {"data": {"added": 2, "updated": 0, "total": 2}}

GET /v1/entities?q=&offset=&limit=, DELETE /v1/entities with {"refs": [...]}. Instant check without saving: POST /v1/screen (up to 100 names).

Matches: GET /v1/matches?status=open&since=2026-10-01T00:00:00Z. Each match has score (0 to 1), reasons, listName, sourceUrl and dates. A match is a possible match: verify it on the official source. Review: POST /v1/matches/{id}/review {"status": "cleared", "note": "Different date of birth"}. Audit log: GET /v1/audit or GET /v1/audit?format=csv.

Dossiers

POST /v1/dossiers {"name": "Example GmbH", "website": "example.de", "country": "DE", "language": "en"}
-> 201 {"data": {"id": "...", "status": "queued"}}
GET /v1/dossiers/{id}      (status: queued, running, ready, failed)
GET /v1/dossiers/{id}.pdf

A request uses one dossier of the month, then one purchased single dossier ($490 each, bought from the dashboard, also beyond the monthly quota); otherwise 402 dossier_quota_exceeded. A dossier_ready alert is sent when it is ready.

Monitoring: sector, regulation, tenders

The profile drives all three services. PUT /v1/profile:

{"languages": ["en"], "countries": ["EU", "US", "IT"], "sectors": ["payments"], "keywords": ["instant payments", "PSD3"],
 "competitors": [{"name": "Example Pay", "website": "examplepay.com"}], "cpv": ["72000000"], "minValue": 100000,
 "tenderProfiles": [{"name": "IT services", "keywords": ["software"], "cpv": ["72000000"], "countries": ["IT", "FR"]}]}

Feed: GET /v1/feed?module=regulation&since=...&limit=50. Items have title, summary in your language, sourceName, sourceUrl, publishedAt, relevance, and for tenders deadline, value, currency. Weekly briefing: GET /v1/briefings?module=tenders&week=2026-W44.

Webhooks

Up to 10 HTTPS endpoints (POST /v1/webhooks {"url": "...", "types": ["match", "tenders"]}; types: match, dossier_ready, news, sector, regulation, tenders; empty = all). Each alert is sent as a POST:

POST https://your.example/hook
Unicorn-Intel-Signature: t=1793000000,v1=<hex HMAC SHA-256 of "<t>.<raw body>" with your whsec_ secret>
Unicorn-Intel-Event-Id: evt_al_...
{"id": "evt_al_...", "type": "alert.match", "created": "2026-10-29T10:00:00.000Z",
 "data": {"kind": "match", "refId": "...", "title": "...", "createdAt": "..."}}

Reply with 2xx within 10 seconds. Failed deliveries are retried after 1, 5, 30, 120, 360, 720 and 1440 minutes. Reject signatures older than 5 minutes. Test: POST /v1/webhooks/{id}/test.

// Node.js
const crypto = require('crypto');
function verify(secret, rawBody, header) {
  const p = Object.fromEntries(header.split(',').map(x => x.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false;
  const mac = crypto.createHmac('sha256', secret).update(p.t + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(mac), Buffer.from(p.v1));
}

Examples

# Python
import requests
H = {"Authorization": "Bearer ui_live_..."}
r = requests.post("https://intel.unicornprivate.com/v1/screen", headers=H, json={"entities": [{"name": "Example Trading LLC"}]})
for m in r.json()["data"][0]["matches"]:
    print(m["listName"], m["score"], m["sourceUrl"])
// JavaScript
const r = await fetch("https://intel.unicornprivate.com/v1/feed?module=tenders&limit=20", { headers: { Authorization: "Bearer ui_live_..." } });
const { data } = await r.json();