Keep a vendor register in sync
Your vendors are already in a procurement system, an ERP or a spreadsheet someone owns. Typing them into Vendorica a second time means two registers that disagree within a month.
This guide sets up a one-way sync: your system stays the source of truth, Vendorica follows.
You need: a key with vendors:write (and vendors:read if you want to
reconcile). How to get one.
One endpoint, two modes
Section titled “One endpoint, two modes”POST /v1/vendors/imports takes up to 10,000 vendors in one request.
The mode you choose decides whether running it twice is safe:
matchKey.mode |
Second run with the same data |
|---|---|
create-only (default) |
Creates duplicates. |
upsert |
Updates the existing rows. |
For a recurring sync you want upsert. create-only is for a one-time
migration into an empty register, where a duplicate means you have made a
mistake and would rather find out.
Pick the match key before the first run
Section titled “Pick the match key before the first run”matchKey.key decides what “the same vendor” means. Change it later and
the next sync will not recognise anything it created earlier — you get a
second copy of your whole register.
| Key | Use when |
|---|---|
name (default) |
Nothing better exists. Fragile: “Acme Ltd” and “Acme Limited” are two vendors. |
website |
Reliable in practice, and usually present. A good default. |
vatNumber |
You are EU-based and your procurement data is clean. The strongest of the four. |
lei |
Financial counterparties. Strongest where it exists, absent for most suppliers. |
A sync run
Section titled “A sync run”curl -X POST https://api.vendorica.com/v1/vendors/imports \ -H "Authorization: Bearer $VENDORICA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "label": "Coupa nightly sync 2026-08-30", "matchKey": { "key": "website", "mode": "upsert" }, "vendors": [ { "name": "Acme Cloud Services", "website": "acme.example", "country": "DE", "vatNumber": "DE123456789" }, { "name": "Northwind Data", "website": "northwind.example", "country": "IE" } ] }'import os, requests, datetime
vendors = [ {"name": v.legal_name, "website": v.domain, "country": v.country_iso, "vatNumber": v.vat} for v in source_system.active_suppliers()]
# The cap is 10,000 per request. Chunk rather than hoping.for i in range(0, len(vendors), 5000): requests.post( "https://api.vendorica.com/v1/vendors/imports", headers={"Authorization": f"Bearer {os.environ['VENDORICA_API_KEY']}"}, json={ "label": f"ERP sync {datetime.date.today()} part {i // 5000 + 1}", "matchKey": {"key": "website", "mode": "upsert"}, "vendors": vendors[i : i + 5000], }, timeout=120, ).raise_for_status()Always send a label. It is how a human finds this run later when they
are asking why a vendor changed. Put the source system and the date in it.
What a vendor object may contain
Section titled “What a vendor object may contain”vendors[] entries are open objects of strings — every value is a
string, up to 4000 characters, and fields the register does not recognise
are ignored rather than rejected. That is deliberate: it means you can hand
over your source system’s rows more or less as they are, and add columns on
your side without coordinating a release here.
Send at minimum a name, plus whatever your chosen matchKey.key needs.
Enrichment
Section titled “Enrichment”Set enrich: true and Vendorica will fill in what it can about each vendor
from its own sources rather than leaving those fields empty.
Leave it off when your source system is authoritative and you would rather see gaps than have them filled by inference — for a regulated register, “we do not know” is often the more useful state than a plausible guess.
Scheduling and reconciling
Section titled “Scheduling and reconciling”-
Run nightly. Vendor registers change on the timescale of contracts, not seconds.
-
Send everything every time, not just what changed.
upsertmakes the full push idempotent, and a full push self-heals a night you missed. Ten thousand vendors per request means most organisations fit in one call. -
Reconcile with
GET /v1/vendors. Count what came back against what you sent. A gap means your match key is not matching what you think it is.
- Uploading documents — file the contracts that go with these vendors.
- Export the audit log — every change this sync makes is attributed to its key.