ServicesVendors Service
API
The vendors service's routes, who may call each one, and the refusals worth knowing about.
Every command takes the usual envelope, {"data": {...}}, and an Idempotency-Key
header. The spec is services/vendors/openapi.yaml.
| Route | What it does |
|---|---|
POST /v1/vendors, GET /v1/vendors | Add a firm; list firms by name, filtered by status, kind, part of the name (q), or a comma-separated list of up to 100 ids |
GET /v1/vendors/{id} | One firm with its people and its insurance now |
POST /v1/vendors/{id}/status | Mark a firm active or inactive |
POST /v1/vendors/{id}/contacts, /contacts/{contact_id}/active | Add a person who may sign in to the vendor portal; let them sign in or stop them |
POST /v1/vendors/{id}/insurance, GET /v1/vendors/{id}/insurance | Record a certificate; list every certificate the firm has given |
GET /v1/vendor-insurance | Every active firm's latest certificate for each coverage, soonest expiry first, filtered by status and coverage |
GET /v1/vendor-portal/contact | The signed-in vendor portal user: their firm, themselves and their colleagues |
Who may call
| Caller | How they prove it | What they may do |
|---|---|---|
| A Flow employee | The Cloudflare Access token for the internal application (VENDORS_ACCESS_AUD) | Read everything; change anything if named in VENDORS_EDITORS |
| A firm's contact | The vendor portal's Access token (VENDORS_PORTAL_ACCESS_AUD), on /v1/vendor-portal/ only | Learn which firm they sign in for |
| Another Flow service | X-Flow-Service-Token matching VENDORS_SERVICE_TOKEN, with X-Flow-On-Behalf-Of naming the person | Read, for that person; never change anything |
A service token on a /v1/vendor-portal/ route acts for the named contact; construction
uses it after checking that contact's portal token itself.
Refusals
| Status | Code | What happened |
|---|---|---|
| 403 | not_a_vendor_contact | The portal user is not an active contact of an active firm |
| 409 | vendor_exists | A firm with that name exists, ignoring case |
| 409 | contact_exists | That email is already a contact, at this firm or another |
| 409 | insurance_exists | That firm already has that certificate: same coverage, policy number and start date |
| 422 | A certificate that expires before it starts, an unknown coverage, kind or discipline, or ids naming more than 100 firms |
Events
Published through the outbox to Service Bus. No event carries a contact's email or name.
| Event | When |
|---|---|
vendor.registered | A firm was added |
vendor.status_changed | A firm was marked active or inactive |
vendor.contact_added | A person was added to a firm |
vendor.contact_access_changed | A person was allowed to sign in, or stopped |
vendor.insurance_recorded | A certificate was recorded |