API changelog
Minor releases add to the contract (new route, optional parameter, response field, enum value); patch releases fix behaviour or docs. Within /v1 nothing is removed or changed in a breaking way: see the deprecation policy. The machine-readable contract is /openapi.json; the service state is on status.
1.39.1 · 2026-10-25
Final prices from the competitor matrix (docs/strategy/2026-10-25-competitor-matrix.md, price flags 3-5); same contract.
GET /v1/plansperCall['/v1/companies/verify'].eurPerCallis 0.05 (was the 0.02 placeholder); still counted as one quota call (mode: quota). TheeurPerCalldescription no longer says placeholder.- Supplier Watch: the dedicated Pro placeholder (EUR 199 / 500 suppliers) is retired; the supplier list keeps using the plan's tracked-company allowance. The inactive Stripe product
arcadium_supplier_watch_prois no longer created bypnpm stripe-setup. - Merger Watch: the Merger Radar tiers carry no standalone price (they are included in the Pro and Business plans); limits are unchanged.
1.39.0 · 2026-10-25
Device Watch portfolio tier for regulatory consultants and EU authorised representatives (additive; version taken after the gambling licence register 1.38.0). Market check and price anchors: docs/research/2026-10-25-srn-portfolio-market.md.
- New
POST /v1/watch/devices/bulk: follow many EUDAMED manufacturers at once fromcsv(every SRN in any column of a client-list export; other columns are ignored and never stored) orsrns. Skips SRNs already followed; the answer's newbulkobject counts added / already followed / over the limit and lists lines without an SRN. 403device_watch_limitwhen nothing can be added over the limit; 400too_many_rowsabove 5,000 lines. DeviceWatchesgainsportfolio(tier or null) andfrequency(dailyfree alert,weeklyportfolio digest);limitis now per account: 10 free, 50 / 250 / 5,000 (fair use, "unlimited") with a portfolio tier.GET /v1/plansgainsdevicePortfolio(free allowance, tiers with prices: Portfolio 50 €79/mo, 250 €199/mo, Unlimited €399/mo; yearly 10 x monthly). Sold by invoice for now (Stripe cataloguearcadium_device_portfolio_*), set on the account withpnpm api-key portfolio <account id> <tier>.- Weekly portfolio digest
pnpm device-watch-send --portfolio(jobdevice-portfolio-digest, Mondays 13:15 UTC): one email for all followed SRNs with the deadline countdown, the week's first devices, new UDI-DIs and certificate changes, manufacturers with no device yet, certificates expiring within 90 days and SRNs EUDAMED does not list. Portfolio accounts no longer get the daily alert. Needs migrationops/017_device_portfolio.sql(no new grants).
1.38.0 · 2026-10-25
Gambling licence register: is a website licensed for gambling, where and by whom (additive; version taken after pharma site register 1.37.0).
- New tag
Gamblingand four routes over the official lists of six regulators (UK Gambling Commission, DE GGL whitelist, SE Spelinspektionen, DK Spillemyndigheden, ES DGOJ, NL Kansspelautoriteit). Needs migrationgambling/001_init.sql, the grants insql/readonly-role.sqlandpnpm gambling load; without them the routes answer 503unavailable.GET /v1/gambling/domains/{domain}: per market the licence holder (company, address country, registry ids), its licences with status and validity, domain status (active / white label / inactive),licensed,match(exact host or same registrable domain),notListedOnwith the day of each list read, and recent events. Anonymous: one domain per call (free tool tier).POST /v1/gambling/domains/check: the same for up to 100 domains; needs a key; one metered row per domain.GET /v1/gambling/operators: licence holders with licences, hosts and registry ids; filtersq,regulator,country,includeRemoved. Anonymous:qrequired, five rows.GET /v1/gambling/events: licence granted / suspended / revoked / ended / reinstated / removed, domain added / removed, operator listed / delisted; filtersregulator,country,type,since. Needs a key.
GET /v1/plans:perCallentries may carry an optionalunit(callordomain); the two licence-check routes are listed at EUR 0.05 (per check, per domain of a bulk call).
1.37.0 · 2026-10-25
Pharma site compliance register (additive; schema pharma, packages/pharma-sites; version taken after Merger Watch 1.36.0).
GET /v1/pharma/sites: EU pharma manufacturing and distribution sites from EudraGMDP (EMA public register) with counts of valid GMP / GDP certificates, MIA / WDA authorisations and active-substance registrations, GMP statements of non-compliance in force, matched FDA inspection classifications (NAI / VAI / OAI) and FDA drug warning letters, astatus(non_compliant,fda_oai,warning_letter,certified,authorised,listed) and the company join (website domain, registry id, method, confidence). Filterscountry,domain,registry_id,status,since,q; cursor paging. Anonymous:domainorregistry_idrequired, 10 rows.GET /v1/pharma/sites/{id}(EudraGMDP site key or OMS location id): documents with links, non-compliance statements, FDA inspections, warning letters and change events.- Supplier Watch: new finding kinds
gmp_non_complianceandfda_warning_letter(plusfda_oai_inspection) for supplier domains joined to a pharma site;sources.pharmatells whether the host has the schema. - Organisations only: no qualified / responsible persons, inspectors or authority contacts; sites whose name reads as a person are left out.
1.36.0 · 2026-10-25
Merger Watch: follow merger-control filings by company, sector, authority, country or keyword and get a daily email when a new filing or a status change matches (additive; version taken after device watch 1.35.0).
- New tag
Merger Watch:POST /v1/watch/mergers(bodykind= domain | registry_id | nace | authority | country | keyword,value),GET /v1/watch/mergers,DELETE /v1/watch/mergers/{id}. The view showstierandlimit(total,companies,topics): free accounts keep 3 rules; the Pro plan carries Merger Radar (50 companies, 5 topics), Business and Scale Merger Radar Pro (1,000 companies, 100 topics). 403merger_watch_limitabove, 400invalid_valuefor a value that does not fit its kind. Needs a self-serve key; not metered; nothing is billed. - New sign-up intent
watch-mergerswith exactly one ofdomain,registryId,nace,authority,countryorq(new optionalSignupIntent.registryId,.nace,.authority): the /mergers/ form's "Email me daily" signs up with it (double opt-in) and the verify page creates the rule. - Anonymous
GET /v1/mergersalso acceptsnaceorsectoralone (still five cases): the /mergers/ form previews the filings of a rule without an email. - The daily
pnpm merger-watch-send(jobmerger-watch, 07:30 UTC, aftermergers-daily) emails an account only on a day with a matching event: notified, phase 2, cleared, cleared with conditions, prohibited, withdrawn, referred, closed (events dated more than 45 days back are a back-fill and skipped). A status move a source states without a dated event now writes an event of the load day. Needs migrationsops/016_merger_watch.sqlandmergers/002_events_seen_at.sql, grantssql/ops-role-merger-watch.sql(pulled in byops-role.sql). GET /v1/account/exportlistsmergerWatches; account erasure deletes them.
1.35.0 · 2026-10-25
Device registration alert: follow an EUDAMED manufacturer and get an email when it registers devices (additive; version taken after mergers 1.34.0).
- New tag
Device Watch:POST /v1/watch/devices(bodysrn, ordomain= every manufacturer SRN of that website),GET /v1/watch/devices,DELETE /v1/watch/devices/{id}. Free, up to 10 manufacturers per account (403device_watch_limitabove). Needs a self-serve key; not metered. - New sign-up intent
watch-devices(withsrnordomain; new optionalSignupIntent.srn): the /eudamed/ checker's "Email me when it registers" button signs up with it (double opt-in) and the verify page creates the watch. - The daily
pnpm device-watch-send(jobdevice-watch, 12:45 UTC, after the EUDAMED refresh) emails an account only on a day with a change of a followed manufacturer: first device registered, new UDI-DIs, certificate issued / withdrawn / expired / expiring. One-click unsubscribe shared with the other digests. Needs migrationsops/015_device_watch.sqlanddevices/002_events_seen_at.sql, grantssql/ops-role-device-watch.sql. GET /v1/account/exportlistsdeviceWatches. Account erasure now also deletes job, recall and device watches (a free account with a job or recall watch could not be deleted before: the rows referenced the account); the api_ops grants forjob_watchesandrecall_watchesgain DELETE, andops-role.sqlnow pulls in the supplier, recall and device watch grants.
1.34.0 · 2026-10-25
Merger filings radar: notified concentrations at three competition authorities (additive; version taken after master's 1.33.0).
- New tag
Mergersand two routes (needs migrationmergers/001_init.sqlandpnpm mergers load, runbookdocs/runbooks/mergers-server.md; without the data they answer 503unavailable):GET /v1/mergers(European Commission DG COMP open data, Bundeskartellamt current proceedings, UK CMA merger inquiries: reference, title, sectors, NACE codes (EC), normalised status pending / phase2 / cleared / cleared_with_conditions / prohibited / withdrawn / referred / closed with the authority's own label, phase, dates, case page and the company parties with role, stated country, resolved domain and registry id with match method and confidence; filtersauthority,country,sector,nace,status,since,party_domain,party_registry_id,party; paged bycursor) andGET /v1/mergers/{id}(one case plus its dated events). - Anonymous calls need
authority,country,party_domainorparty_registry_idand get at most 5 rows; one case is a point lookup. - Company-level only: parties that read as natural persons are never stored (counted in
withheldParties, the title reads "[person]"); case handlers and advisers are not stored.
1.33.0 · 2026-10-25
Activation and quota nudges for Free keys (additive; version taken after consent radar 1.32.0).
- Free keys from 80 % of the monthly quota get two response headers:
x-quota-warning(80, or100from the last call of the quota on) andx-upgrade-url(the plans page). Both are exposed to browsers (CORS). Paid plans are not affected. - The
quota_exceeded429 of a Free key carries an optionalupgradefield in the error body (url,message,nextPlan,monthlyQuota,priceEurPerMonth); theErrorschema lists it. - Quota hits are recorded once per account, threshold and month (migration
ops/014_activation.sql, tableops.quota_hits); the hourlypnpm api-onboarding-sendsends one email per threshold and month, plus the onboarding emails (welcome, day-2 first-call nudge while no call was made, day-7 usage summary). All carry the one-click unsubscribe of the digests and respect it.
1.32.0 · 2026-10-25
Consent radar: which consent-management platform and trackers company websites load (additive; version taken after emissions 1.31.0).
- New tag
Consentand three routes (needs migrationconsent/001_init.sqlandpnpm consent-scan, runbookdocs/runbooks/consent-server.md; without the data they answer 503unavailable):GET /v1/consent/market(CMP vendor shares and tracker prevalence percountryorsegment, adoption, counts per static-HTML signal and the monthly history),GET /v1/consent/companies/{domain}(CMPs, trackers with category, tracker scripts with no consent hold-back marker in the delivered HTML, Consent Mode / TCF flags, scan history and changes) andGET /v1/consent/switches(CMP switched / added / removed between two monthly scans; filtersdomain,from_cmp,to_cmp,country,kind,since; paged bycursor). - Anonymous calls: market is a preview (one country or segment per call), a company stack is a point lookup, the switch list needs
domain(5 rows) or a key. - Technical detection of public HTML only (one plain GET of the home page per month, plus the public GTM container script when the page loads a tag manager and no CMP). No verdicts: the "scripts without consent gate" field is a plain-fetch observation. No personal data.
1.31.0 · 2026-10-25
Company-level emissions for CBAM and financed-emissions reporting (additive; version taken after master's 1.30.0).
- New
GET /v1/emissions/companies(searchEmissionsCompanies): operators (legal entities only) of the EU Emissions Trading System, largest emitter first, cursor pagination. Per operator: verified emissions and free allocation per year since 2013, the allocation gap of the latest year (allowances to buy; CBAM phases free allocation out from 2026), installation count, sectors and CBAM goods sectors (cement, iron_steel, aluminium, fertilisers, hydrogen), the five biggest installations, and the join to LEI, website domain (domainMethod: lei or registry_id) and ultimate parent LEI and domain (GLEIF Level 2) where the EU Company ID table proves the link. Filters:domain(the operator's own or its ultimate parent's: group view withmatched: parent),lei(operator or ultimate parent),country,sector. Anonymous callers: one ofdomain,leiorcountry, 5 rows, no cursor. - New
GET /v1/emissions/installations/{id}(getEmissionsInstallation): one installation, aircraft operator or shipping company (ids likeeutl:DE:975) with yearly emissions and allocation, the Union Registry compliance code (A, B, C, EXCLUDED SINCE year, with acomplianceLabel), its operator, change events (new installation, emissions jump or drop of 25% and more from 10,000 t, compliance change, account closed) and, where the Industrial Emissions Portal facility states the ETS id, its parent company and latest pollutant releases. - MCP tool
company_emissionson the same data. Sources and licences: European Commission Union Registry (CC BY 4.0, "Source: European Commission, Union Registry of the EU ETS"), EEA Industrial Emissions Portal (CC BY 4.0, European Environment Agency), GLEIF (CC0). Account holders that are not companies are left out; no coordinates or addresses.
1.30.0 · 2026-10-25
Partner referral code (additive; version taken after Planning 1.29.0).
POST /v1/account/signupaccepts an optionalref: the partner code from a?ref=link (3-32 lowercase letters, digits or hyphens; anything else is ignored, never an error). It is kept with the emailed link, stored once on the new account (first code wins) and copied into the Stripe Checkout session and subscription metadata asref.GET /v1/meaccount.referralCode: the partner code the account signed up with, ornull.- Needs ops migration
013_referral.sql(two nullable columns, one index). The partner statement (pnpm partner-statement --month YYYY-MM,docs/partners.md) joins Stripe invoices to the code.
1.29.0 · 2026-10-25
Planning: UK and Ireland construction project leads (additive; version taken after Recall Radar 1.28.0).
- New tag
Planningand two routes (needs migrationplanning/001_init.sqlandpnpm planning, runbookdocs/runbooks/planning-server.md; without the data they answer 503unavailable):GET /v1/planning/applications(non-householder commercial and large residential planning applications: authority, reference, description, type, kind, units / floor area, status submitted / granted / refused / withdrawn / appealed / decided, dates, town and postcode district, the authority's record URL and the company applicant with Companies House number and domain where published; filterscountry,authority,type,kind,status,min_units,min_floor_area,changed_since,with_applicant; paged bycursor) andGET /v1/planning/companies/{domain}(planning activity of one developer plus its construction-works contract awards from the tender index). Anonymous calls needcountryorauthorityand get at most 5 rows. There is nomin_value: none of the open feeds publishes a project cost. - Legal entities only: an applicant that reads as a natural person is never returned (and never stored); agents, architects, case officers, e-mail addresses, phone numbers and street addresses are not stored. Ireland's dataset publishes no applicant at all. Sources: National Planning Applications (Department of Housing, CC BY 4.0), London Borough of Camden, City of Bradford MDC and Northumberland County Council (Open Government Licence v3).
1.28.0 · 2026-10-25
Recall Radar (additive): product safety alerts and the marketplace listings that match them.
GET /v1/recalls: EU Safety Gate, US CPSC and UK OPSS alerts, normalised (product, brand, model, GTIN barcodes with a verified check digit, category, risk type, measures, the marketplace listings the authority names, links to the official page and images). Filtersq,source,country,category,brand,riskType,barcode,since,until,withMatches; cursor pagination. Anonymous: withbrand,barcodeorq, at most 10 rows.GET /v1/recalls/matches: live Amazon, AliExpress, Etsy and TikTok Shop listings that match an alert, by the listing the alert names (confidence 0.99), by barcode (0.97) or by brand plus model code or name (0.80-0.93). Each match carriesnotice("Listing matches a recall alert. Verify before acting."), listing URL, price, the marketplace seller id (never a name) and first / last seen. Filtersmarketplace,brand,category,alertId,minConfidence,since. Anonymous: withbrandoralertId, at most 5 rows.- Recall Watch:
POST|GET /v1/watch/recalls,DELETE /v1/watch/recalls/{id}(self-serve key, up to 5 brands, weekly emailpnpm recall-watch-send, same one-click unsubscribe as the other digests). Needs migration012_recall_watch.sqlandapps/hiring-api/sql/ops-role-recall-watch.sql. - Data: schema
recalls(packages/recalls), loaded weekly bypnpm recalls load; runbookdocs/runbooks/recall-radar-server.md.
1.27.0 · 2026-10-25
Medical devices: EU EUDAMED x US FDA (additive; version taken after energy 1.26.0).
- New tag
Medical devicesand three routes (needs migrationdevices/001_init.sqlandpnpm devices, runbookdocs/runbooks/devices-server.md; without the data they answer 503unavailable):GET /v1/devices/manufacturers(manufacturers registered in EUDAMED: SRN, seat, website domain, registry / VAT ids of the domain, devices by risk class, valid certificates and notified bodies, EU authorised representative flag for non-EU manufacturers, matched FDA establishment registrations; filtersdomain,srn,q,country,risk_class,us_cleared,no_eu_ar,cert_expiring,no_devices),GET /v1/devices?manufacturer_domain=ormanufacturer_srn=(UDI-DI rows of one manufacturer with its certificates and FDA matches; paged bycursor) andGET /v1/devices/events(new registrations, certificates issued / expiring / withdrawn; key required). Anonymous calls needdomain/srn(ormanufacturer_domain/manufacturer_srn) and get at most 10 rows. These routes use snake_case filter names (manufacturer_domain,risk_class) as specified for the product. - Legal entities only: economic operators whose name reads as a natural person are never returned; contact persons, e-mail addresses, phone numbers and street addresses are not stored (the website domain is the registrable domain of the published mailbox host). Sources: EUDAMED public data (European Commission, reuse under Decision 2011/833/EU) and openFDA registration & listing (public domain).
1.26.0 · 2026-10-25
Grid-connection and renewable project pipeline (additive; version taken after master's 1.25.0).
- New
GET /v1/energy/projects(searchEnergyProjects): wind, solar, storage, biomass and hydro projects of 1 MW and up, largest first, cursor pagination. Filters:country(DE, GB),technology,minMw,status(planned, permitted, under_construction, in_operation, shut_down, decommissioned),changedSince(status, capacity or dates changed in a load cycle),region(DE Bundesland),operatorDomain. Germany: Marktstammdatenregister units incl. planned ones, Bundesland / district / municipality, grid operator, operating company with website domain and registry id where known. Great Britain: NESO Transmission Entry Capacity register and Embedded register (Gate 1/2, consent stage, connection date). Companies only: natural-person operators are left out, no coordinates, no street addresses. Anonymous callers: one country or technology, 10 rows, no cursor. - New
GET /v1/energy/projects/{id}(getEnergyProject): one project with its change history (new project, status change, capacity change, moved date, removed), ids likede_mastr:SEE940146675093,gb_tec:PRO-003804. - MCP tool
energy_projectson the same data. Sources and licences: Marktstammdatenregister (Bundesnetzagentur, DL-DE-BY-2.0) and NESO Open Data Licence ("Supported by National Energy SO Open Data").
1.25.0 · 2026-10-25
Clinical-trial pipeline by sponsor (additive; after Supplier Watch 1.24.0).
- New
GET /v1/trials(listTrials): trials from ClinicalTrials.gov (public domain) and the EU CTIS public portal, one record per trial (records that cite each other, by NCT / EU CT / EudraCT / ISRCTN number, are merged), newest change first. Filters:sponsor(company website domain),sponsorClass,phase,status,condition(condition or MeSH words),area(condition area),country,changedSince; cursor paging. Each trial: ids, title, phase, status, conditions, MeSH terms, intervention types, countries, start and primary completion date, enrolment target, number of sites, sponsor organisation, type and company domain. Anonymous: only withsponsor,conditionorarea, a 5-row preview, one value ofphase/status/country, no cursor. - New
GET /v1/trials/sponsors/{domain}(getTrialSponsor): the pipeline of one sponsor company: trials by phase, status, area and country, trials first posted in the last 90 days, its newest trial changes (new trial, phase move, status change, moved dates), open clinical and regulatory roles on its own career sites, public contract awards and registry ids. Anonymous point lookup. - Organisation-level only: no investigators, contacts, e-mails, phones or site names; a sponsor that could be a private person is withheld. New schemas
Trial,TrialsPage,TrialChange,TrialSponsorProfile; new tagClinical trials. MCP toolclinical_trialsreads the same routes. ISRCTN is not served (its terms forbid building a database).
1.24.0 · 2026-10-25
Supplier Watch (additive): a supplier list with a risk digest by email, and a point lookup.
POST /v1/watch/suppliers(self-serve key): upload up to 2,000 suppliers per call as CSV text (csv) or JSON rows (suppliers): a websitedomain, avatnumber with its country prefix, a registryid+country, or a registeredname+country. The answer carries a match report (match): rows matched / ambiguous / not found / withheld (sole traders and natural persons are withheld and never stored), invalid rows, duplicates, suppliers added and suppliers left out by the plan limit. The list size is the plan's tracked-company allowance (GET /v1/planstrackedCompaniesIncluded); over it the call answers403 supplier_limit.GET /v1/watch/suppliers(paged withlimit/offset) andDELETE /v1/watch/suppliers/{id}.- The account email gets a "Supplier risk digest" (
pnpm supplier-watch-send): weekly on the chosen weekday, daily on Pro, Business and Scale. Per supplier, the changes since the last digest ranked dissolved / insolvency / strike-off > VAT invalid > unreliable VAT payer > accounts overdue > contract won > hiring freeze, each with a link to the official source. Same one-click unsubscribe as the other digests. GET /v1/suppliers/risk?domains=(anonymous point lookup: one domain without a key, up to 10 with one): the company behind each domain, the stored register status and the ranked findings of the lastdays(default 90). Stored data, no live call.- Migration
011_supplier_watch.sql(ops.supplier_lists,ops.supplier_watches); grants insql/ops-role-supplier-watch.sqland thetaxflags/vies_checksblock ofsql/readonly-role.sql.
1.23.0 · 2026-10-25
Final prices (additive, one plan-table change).
- New self-serve plan
scale(EUR 999 a month): 4,000,000 calls a month, 1,200 requests a minute, 200,000 tracked companies (4x Business calls and tracked companies at 2x the price).POST /v1/account/checkoutand the sign-upplanintent accept"scale";GET /v1/planslists it with its monthly and yearly price. Needs migration010_scale_plan.sql(plan checks) andpnpm stripe-setup(pricesarcadium_api_scale_month|year) before it can be bought. - Yearly billing is now "2 months free" for every paid plan: 10 times the monthly price (Starter 490, Pro 1,990, Business 4,990, Scale 9,990),
annualDiscountis 1/6 (was 0.15, prices were 15% off). New fields inGET /v1/plans:annualFreeMonths(2) andfounding(the founding price: codeFOUNDING29, Starter at EUR 29 a month for 90 days, first 100 accounts; a Stripe promotion code with max_redemptions 100, entered at checkout). Existing yearly subscriptions keep the price they bought. - Bid Desk (EUR 390 / 890 a month, 3,900 / 8,900 a year) and the data licences are billed outside this API, by Stripe payment links and Stripe Invoicing created with
pnpm stripe-setup. They have no API route.
1.22.1 · 2026-10-25
Defence sector precision (behaviour fix, same contract).
sector=defencenow means defence and security relevant procurement only. A defence ministry's or armed force's purchases of civilian commodities (medicines, food, fuel, furniture and cleaning, printed matter, office supplies, catering, health and cleaning services, ordinary clothing, transport) no longer match unless the notice states Directive 2009/81/EC, a defence or security CPV code or a military / security word in the title. Those notices carry a separate internal flag (defence_buyer_other) that is not exposed by the API. Notice counts undersector=defencedrop by about 29% after the server re-classification (docs/runbooks/defence-reclassify.md). Rule and audit:docs/research/2026-10-24-defence-classifier-audit.md.
1.22.0 · 2026-10-25
GDPR self-service (additive).
GET /v1/account/export(key auth, not metered, 10 an hour): everything held for the account as JSON: email, company domain, plan, dates, billing state, key metadata (never the secrets), watchlists, Competitor Watch and Tender Watch settings, usage counters per month and route.DELETE /v1/accountwith{"confirm":"delete"}(key auth, 3 an hour): cancels a paid Stripe subscription at once when billing is on (a Stripe failure answers 502 and deletes nothing), revokes and unlinks every key, deletes watches and watchlists and erases the email. An account that ever had a Stripe customer keeps, without the email, only the customer id, company domain, plan and dates for 10 years (retainedin the answer); any other account row is deleted.- Retention: sign-up links are deleted after 48 hours, unverified accounts after 48 hours (daily
pnpm api-anon-watch; needssql/ops-role-retention.sqlon the server). Seedocs/gdpr.md.
1.21.0 · 2026-10-25
Remote jobs, direct from employers (additive; version taken after master's 1.20.0).
- New
GET /v1/jobs/remote(searchRemoteJobs): the free search behind https://arcadiumdata.io/jobs/remote/ and the MCP toolremote_jobs. Same rows and the same stored-tsvector / in-flight-cap path asGET /v1/jobs, withremoteforced on,region(europe,uk,us,worldwide= remote jobs that list no country) anddays(first seen in the last N days). Anonymous behaviour (owner decision 2026-10-25): free and ungated on this route only. Anonymous callers get up to 50 jobs per call and may page withcursor; they stay under the per-IP and subnet limits, the in-flight cap and the route's daily anonymous budget (20,000 database reads a day, then cache-only).GET /v1/jobskeeps its rule (key required). Newx-anonymouswording: "anonymous with paging". GET /v1/jobsgets an optionalseenSince(YYYY-MM-DD): first seen by us on or after that day. UnlikepostedSinceit also covers jobs without a posting date.- New Job Watch (weekly email alerts for a saved remote-job search):
POST/GET /v1/watch/jobs,DELETE /v1/watch/jobs/{id}(up to 5 per account,dailyis refused with 403plan_requireduntil a paid plan exists). New sign-up intentwatch-jobs(q,region,frequency). - Sign-up behaviour change:
companyDomainis optional onPOST /v1/account/signupwhen the intent iswatch-jobs(a job seeker has no company website). The account then stores the reserved placeholderjobseeker.invalid. Freemail addresses were already accepted as the sign-in email; the disposable-inbox refusal and the sign-up rate limits are unchanged. Every other sign-up still needs a company domain that is not freemail.
1.20.0 · 2026-10-25
UK Companies House register (additive).
GET /v1/companies/resolvematches carrysectorCodes(array or null): the register's sector codes, GB up to 4 SIC 2007 codes with the primary first, CZ the NACE code.statusSourcecan now begb_ch.- Great Britain is answered from the monthly Companies House snapshot of live companies (
gb_ch, Open Government Licence v3.0):resolveby Companies House number (type=uk_crnorcountry=GB), by name, and by a domain whose legal notice states the number returns legal name, category, status and SIC codes. GET /v1/companies/verify?id=<number>&country=GBanswers from that snapshot:register.sourceisgb_chand the new optionalregister.basisissnapshot(other registers answerlive). A number that is not in the snapshot (dissolved before we held it, or never registered) answersnot_found; officers and persons with significant control are never read or returned. Needs registers migration005_gb_ch.sqlandpnpm registers-gb-ch(runbookdocs/runbooks/uk-companies-house-server.md).
1.19.0 · 2026-10-25
UK gender pay gap and licensed visa sponsors on the company profile (additive; 1.18.0 is the billing flag on master).
GET /v1/companies/{domain}gains two optional fields, bothnullwhen none or on a host without the data:ukPayGap(latest UK gender pay gap report of the company, joined through its Companies House number: median and mean hourly gap, bonus gaps, share of women in the top quartile, size band, late flag, the employer's own report page, history by year) andvisaSponsor(entry on the Home Office register of licensed sponsors: routes, ratings, town, register date). Company level only; the person named in the filing is never stored. Both are Open Government Licence v3.0 data. Needs registers migration004_uk_open.sqlandpnpm uk-open(runbookdocs/runbooks/uk-paygap-sponsors-server.md).
1.18.0 · 2026-10-25
Billing visibility (additive).
GET /v1/plansandGET /v1/mereturnbilling: boolean: true when self-serve checkout works on this host, false when paid plans are not open yet (checkout answers 503). The site hides the upgrade buttons when it is false.
1.17.0 · 2026-10-25
UK Contracts Finder (additive).
sourceaccepts a new valuecf(UK Contracts Finder: England's below-threshold opportunities and awards, plus legacy PCR 2015 notices) onGET /v1/tendersand inTender.source. No new route or field:cfrows come through/v1/tenders,/v1/tenders/expiring(award rows with a contract end),/v1/tenders/leadersand the MCP tender tools like any other source; buyer country isGB, supplier ids areuk_crn:(Companies House) where the notice states one. A Contracts Finder notice that copies a Find a Tender notice (same buyer, title and kind within 3 days, no contradicting value or deadline) is not listed twice: the CF row is a duplicate of the FTS row.- Supplier names without a Companies House number must carry a company or public-body form to be listed (sole traders are counted in
winnersWithheld).
1.16.0 · 2026-10-25
UK Procurement Act notice views (additive).
GET /v1/tenders/expiring: new optionalkind=pipeline(UK1 pipeline and UK3 planned procurement notices),terminated(UK11 contract termination) orchanged(UK10 contract change), UK Find a Tender only. Thefrom/towindow applies to the contract end the notice states. Withoutkindthe answer is unchanged (award notices).ExpiringContractrows gain optionalnoticeCode(Procurement Act 2023 notice codeUK1..UK17; null for other sources). Needs ops migrationtenders/009_notice_code.sqland a re-read of the UK days (runbookdocs/runbooks/uk-fts-backfill-server.md).
1.15.1 · 2026-10-25
POST /v1/account/signupanswers503 signup_closedon a production host without SMTP (magic links would only reach the log). Same contract; every other route and the anonymous tier are unchanged.POST /stripe/webhookrefuses an event whoselivemodedoes not match the host (400 livemode_mismatch), and a production host with a Stripe test key runs with billing off unlessSTRIPE_ALLOW_TEST=on.
1.15.0 · 2026-10-24
Defence & Security Procurement Radar (additive).
- New optional
sectoronGET /v1/tenders,GET /v1/tenders/expiringandGET /v1/tenders/leaders:defence= defence and security procurement (defence ministries, armed forces and their procurement and logistics agencies, TED notices under Directive 2009/81/EC, military CPV codes, police / border / customs / prison buyers of security equipment; fire brigades, civil protection and military hospitals left out). Precision of the classifier on a hand-checked sample of 200 notices: seedocs/research/2026-10-24-defence-classifier-audit.md. GET /v1/tenders/expiring: new optionalframeworksOnly=true(framework agreements only).GET /v1/tenders/leaders:sectorcounts as the narrowing filter (nocountry/cpv/qneeded) and is always answered live;filter.sectorechoes it; winner rows gainregistryId(type:value) when the notices name the winner alone with one company id (companies-only rule of 1.14.0; null otherwise, absent from rollup answers).POST /v1/watch/tenders: optionalsector(defence); a saved search may be the sector alone.TenderWatchrows carrysector. Sign-up intentwatch-tendersacceptssector. Needs ops migration007_tender_watch_sector.sql.
Also in this release (no contract change):
- Performance (security review R1, slow queries an anonymous caller could trigger):
GET /v1/jobs?q=runs on a stored search vector in two phases once the server's backfill is done (same matches, same order);minValueEuronGET /v1/tendersandGET /v1/tenders/expiringuses an index;GET /v1/tenders/leaderswithqreads the matching notices once instead of three times;POST /v1/coveragecounts in the database. The only visible difference:paybands with the samejobsandcurrencyare now ordered byperiod(was arbitrary).
1.14.0 · 2026-10-24
EU Company ID: companies only for registry ids (additive field, stricter data).
GET /v1/companies/resolve: new fieldwithheld(count of ids left out). An id a sole trader or natural person can also hold (FR SIREN / TVA, CZ IČO, IT partita IVA, PL NIP / REGON, DE HRA and VAT, NL KvK, BE KBO, AT FN, NO orgnr, FI Y-tunnus, other VAT numbers) is returned only when a stored register row with a company legal form (FR SIRENE / BODACC, NO Brønnøysund, FI PRH, PL KRS) or a GLEIF record holds it, or, for countries without a stored register, a company-only id of the same country (DE HRB, UK company number, PL KRS, ES entity NIF, SE organisationsnummer) sits on the same domain. A person's own number by pattern (CZ VAT of 9-10 digits, BG VAT of 10, PT 1xx-3xx, LV personal codes, ES DNI/NIE) is never returned. An id query that only matched a withheld id answersfound: falsewithwithheld> 0.GET /v1/companies/{domain}:registryIdsfollows the same rule (shape unchanged).
1.13.0 · 2026-10-24
EU Company ID (additive).
- New
GET /v1/companies/resolve(CompanyResolve): exactly one ofdomain,name+country, orid(+ optionaltype:vat,leior a national id type, orcountry). Stored data: the company's domain, registry / VAT / LEI ids withsources,confidenceandobservedAt, VAT, LEI with its GLEIF status, legal name, legal form, country and the status the national register last showed (NO, FI, FR),asOf. Nothing found = 200 withfound: false. Anonymous: point lookup, at most 3 matches. - New
GET /v1/companies/verify(CompanyVerify):vat, orid+country. Live check in the open national register (NO Brønnøysund, FI PRH/YTJ, FR recherche-entreprises + stored BODACC, CZ ARES) and in the European Commission's VIES for the VAT number, cached 24 hours.statusaddsnot_found,not_company(sole trader / natural person: nothing else is returned) andunknown(sources did not answer);statusBasissays where the status comes from. Anonymous: point lookup with its own lower daily budget (300 database-miss calls a day). - Both routes sit before
/v1/companies/{domain}, which therefore no longer treatsresolve/verifyas a domain (neither was a valid company domain before). GET /v1/plans: new fieldperCall(routes priced per call;/v1/companies/verifyplaceholder €0.02, counted as one quota call until per-call billing is switched on).
1.12.0 · 2026-10-24
POST /v1/account/signup: new optional body fieldintent(SignupIntent): what to set up after the email is confirmed, a free-tool action (watch-company+domain,watch-tenders+country/cpv/q,pay-csv+role) and/or a paidplanto upgrade to. It is kept with the emailed link (24 hours) and an invalid one is refused with 400 before any email goes out.POST /v1/account/verify: new response fieldintent(the intent sent with the sign-up, or null), so opening the link on another device still finishes the setup.
1.11.0 · 2026-10-23
GET /v1/companies/{domain}: new response fieldregistryIds(national registry, VAT and LEI ids of the company, with type, canonical value, confidence and sources: the company's own legal-notice page, Wikidata, GLEIF, national registers). A domain known only by its registry ids now answers 200 instead of 404. Point lookup only (anonymouspointrule unchanged): no route lists or searches ids, so nothing new is listable without a key; at most 20 ids per domain.- Company Pulse:
tender_awardedevidencematchmay now beregistry_id(the winner's national / VAT id on the award notice equals an id the company states), as exact aswebsite.
1.10.0 · 2026-10-23
Policy change for anonymous callers (no key); the contract for keyed and service callers is unchanged (same routes, parameters, fields, page sizes and limits). Which calls work without a key is policy, not contract (docs/api-versioning.md "Anonymous tier"), so it changes within /v1.
- Anonymous = point lookups only. Every
auth: optionaloperation states its rule in a newx-anonymousextension.GET /v1/jobs,GET /v1/pulse/eventsandGET /v1/eventsneed a key (401key_required);GET /v1/ats/switchesneedsdomain,GET /v1/tendersneedswinnerDomain,GET /v1/pay/bandsneedsroleorisco(one country, one group),GET /v1/reviews/panelneeds onetickerorq;GET /v1/tenders/leaders,GET /v1/ats/marketandGET /v1/pay/transparencytake one value per filter.cursoralways needs a key. - Anonymous answers are a preview: at most 5 rows per list on list and aggregate routes (14 nights of a rate curve, 28 panel rows),
nextCursoralways null, descriptions cut to 280 characters,x-arcadium-anon: trueon every anonymous answer and a newanonymousfield (preview,rowCap,truncated,signup,note). POST /v1/coverage: at most 10 domains per call without a key (50 with one).- New limits without a key: per subnet (IPv4 /24, IPv6 /48) on top of per IP, a daily budget of anonymous database reads per route, and strict mode (
503 anon_strict, Retry-After: only recently cached answers) when a budget runs low, after repeated global-cap trips, or when the operator setsANON_MODE=strict. The global anonymous cap is now 300 calls/minute (was 1,200). Optional deny list of hosting/proxy networks for anonymous calls (401key_required). GET /v1/plans: new fieldanonymousPolicy. OpenAPI: new503response on operations open to anonymous callers.- Share-type fields (
share,payShare,remoteShare, ...) may differ from the stored value below the 6th decimal; rounded to 6 decimals they are exact. - New tender routes of 1.9.0 without a key:
GET /v1/tenders/expiringandGET /v1/tenders/marketsare previews (onecountryand onecpv, top 5 rows per list, no cursor);GET /v1/tenders/suppliers/{id}is a point lookup with lists capped at 5.
1.9.0 · 2026-10-23
- Tenders:
GET /v1/tenders/expiring(new, Re-tender Radar): awarded contracts whose contract ends betweenfromandto(default today + 18 months), soonest first, with current holders (+ website domain when stated), value band (framework ceilings flagged), end-date basis, renewals and the expected re-tender window; cursor pagination. - Tenders:
GET /v1/tenders/suppliers/{id}(new, Contracts Intelligence): supplier profile by website domain or supplier key: awards, buyers, buyer concentration (HHI), CPV divisions, countries, monthly timeline, contracts ending in the next 18 months, latest awards. - Tenders:
GET /v1/tenders/markets(new): one market (countryand/orcpv): top winners and buyers, HHI of award and value shares, top-1/3/10 share, median award, award vs estimated value, cross-border share, repeat buyer-supplier pairs, awards per month.
1.8.0 · 2026-10-23
- Free tools tier (new): the read routes behind the free site tools (
/tools/*,/lookup/<domain>/) are markedx-tool: truein the OpenAPI document. Anonymous calls there use their own per-IP bucket (30/min, 300/day instead of 10/min, 100/day), may be answered from a shared 10-minute answer cache (x-cache: hit|miss,age) and carrys-maxage+stale-while-revalidate. Every anonymous call that reaches the database also counts against one global per-minute cap (429 "busy"; keys never count). Limits inGET /v1/plansanonymousTools(new field). Routes: companies profile, history and pulse, ATS switches, pay bands, tenders, tender leaders, shops. GET /v1/tenders/leaders(new): top winning organisations and top buyers of award notices for acountry,cpvand/orqin the lastmonths(default 12), plus the 5 newest award notices.GET /v1/tenders: new optionalwinnerDomain(notices won by a company domain).GET /v1/ats/switches: new optionaldomain(switches of one company).GET /v1/pay/bands: new optionalrole(a job title, mapped to its ISCO-08 group); response fieldrole.- Tender Watch (new):
POST /v1/watch/tenders(countries, CPV prefixes, keywords, weekday),GET /v1/watch/tenders,DELETE /v1/watch/tenders/{id}: a weekly email with the new awards and open calls of a saved search (free during the beta, 5 per account;pnpm tender-watch-send, migration004_tender_watch.sql). GET /badge/hiring/{domain}.svg(new, outside/v1): an embeddable SVG badge with the open-jobs count, cached 1 hour, global cap only (a busy host serves a neutral badge).
1.7.0 · 2026-10-23
- Company Pulse: new event types from official company registers and EU grants, keyed to the company domain the register states (or a VAT / name + country match, see evidence
domainMatchanddomainConfidence):register_registration,register_bankruptcy,register_restructuring,register_liquidation,register_dissolution,name_change,hq_moved,capital_increase,capital_decrease,headcount_band_change,sector_change,accounts_filed,business_sale(France BODACC: the company bought a business) andeu_grant_won(CORDIS Horizon Europe, withecContributionEur). Registers: Norway Brønnøysund, Finland PRH, France SIRENE + BODACC. Evidence carriesregister,registryId,companyand aurlon the register; never a person. - Pulse event
sourceaddsregistersandeu_grants;sources(PulseSources) adds the same two booleans. - Score: two new components,
corporate(max 10: insolvency, liquidation and dissolution count against, headcount band up / capital increase for) andpublic_funding(max 6, EU grants).
1.6.0 · 2026-10-23
- Competitor Watch (new): a weekly email digest per competitor domain (hiring by function and country against a 4-week baseline, new countries, tools named in job ads, posted pay, reviews, public contracts won, ATS switches, each with dated evidence links).
POST /v1/watch/competitors(domains +weekday),GET /v1/watch/competitors(watches,limit,freeMonth,unsubscribed),DELETE /v1/watch/competitors/{domain},POST /v1/watch/checkout(Stripe Checkout for the add-on:competitor_watch_singleper competitor orcompetitor_watch_10) andPOST /v1/watch/unsubscribe?token=(RFC 8058 one-click, no key). Needs a self-serve key; not metered. GET /v1/plans: new fieldaddons(Competitor Watch prices, free first month).
1.5.0 · 2026-10-23
- Tenders: new response field
winnerDomainson every tender (GET /v1/tendersand the tender objects elsewhere): the company domains of the winners, from the organisation websites the notice states (TED winner internet address, attributed to the winner names; possible persons, buyers, portals and public-sector sites dropped). Empty when the notice states none. Use it to join a tender to/v1/companies/{domain}. - Company Pulse:
tender_awardedevidencematchis nowwebsite(stated winner site) orcompany_name(unique name key + country, as before); itswinnermay be null when the stated site spells no winner name. Review events may carrymethod: stated(the developer site the App Store / Google Play listing states).
1.4.0 · 2026-10-23
- ATS market (new):
GET /v1/ats/market(monthly ATS share since February 2023 among the employers observed in the public web archive, wins / losses / dated switches per vendor, one segment per call bycountryorsizeBand,series=core4|all5, plus today's live share across 10 ATS) andGET /v1/ats/switches(companies that switched ATS, keyed by domain, dated, with evidence and confidence; filtersfromAts/toAts(aliasesfrom_ats/to_ats),since,country,includeLeverGap; cursor paging).
1.3.0 · 2026-10-23
- Account (new): self-serve sign-up and billing.
POST /v1/account/signup(work email + company domain + accepted terms; emails a one-time link, 202),POST /v1/account/verify(redeems the link, returns a Free key once),POST /v1/account/checkout(Stripe Checkout for Starter, Pro or Business,intervalmonth or year),GET /v1/account/portal(Stripe Customer Portal). Checkout and portal need a key but are not metered. GET /v1/me: new fieldsremainingThisMonth,overageThisMonth,quotaResetsAt,requestsPerMinuteandaccount(company domain and billing status of a self-serve key). It no longer counts against the quota and answers at the quota too.GET /v1/plans: new planbusiness(€499 a month); per-planpriceEurPerYear,selfServe,overageEligible; top-levelannualDiscount(0.15),overage(the policy;hard_stopfor now) andsignup.- New response header
x-quota-overagewhen soft overage is switched on (off by default).
1.2.0 · 2026-10-23
- Companies:
GET /v1/companies/{domain}/history(new): point-in-time hiring history since February 2023 from the Common Crawl archive, one row per job board per crawl (observedAt,availableAt, coverage flag) plus a per-crawlmonthssummary; optionalfrom/to.
1.1.0 · 2026-10-23
- Tenders:
GET /v1/tenderssourceadds national below-threshold sourcesboamp(FR),bund(DE),bzp(PL),eop(BG).
1.0.0 · 2026-10-23
First versioned release of the /v1 contract (snapshot openapi.v1.json):
- Jobs:
GET /v1/jobs,GET /v1/jobs/{id}. - Companies:
GET /v1/companies/{domain},GET /v1/company/{domain},GET /v1/company/{domain}/signals,POST /v1/coverage,GET /v1/events. - Company Pulse:
GET /v1/companies/{domain}/pulse,GET /v1/pulse/events. - Pay:
GET /v1/pay/bands,GET /v1/pay/transparency. - Hotels:
GET /v1/hotels/rate-curve,GET /v1/hotels/rate-curve/{city}. - Shops:
GET /v1/shops/{domain},GET /v1/shops/{domain}/apps. - Tenders:
GET /v1/tenders. - Reviews:
GET /v1/reviews/snapshot,GET /v1/reviews/panel. - Watchlists and account:
/v1/watchlists,GET /v1/plans,GET /v1/me. Deprecation/Sunset/Linkheaders on deprecated routes (none deprecated yet);/healthreports the deployedrelease(git SHA) when the image sets one.