VendBuddy / Developers

API and webhooks

Everything VendBuddy holds for your operation, in JSON, under your own key: revealed contacts, your pipeline, your machine registry and daily sales. Push sales in from any telemetry platform, ERP or spreadsheet. Included with Starter and Pro

Authentication

Create a key in the app under Connect Machines. It is shown once. Send it on every request:

curl https://vendbuddy.io/api/v1/me -H "Authorization: Bearer vb_live_..."

Limits: 5 active keys, 120 requests a minute per key. Revoke a key any time in the app.

Endpoints

GET /api/v1/mePlan, credits and the limits of your plan.
GET /api/v1/leads/revealed?limit=100&since=ISOThe contacts you have revealed: company, name, title, email, phone, website, city, state, ZIP, verification.
GET /api/v1/pipeline?stage=ContactedYour pipeline cards as one list, each with its stage, contact, score, notes and created_at. stage is optional.
GET /api/v1/machinesYour machine registry with per-machine stats (revenue, last visit, days since service).
GET /api/v1/sales?from=YYYY-MM-DD&to=YYYY-MM-DD&machine_id=Daily sales rows: date, machine, amount, units, cash, card, product mix, source.
POST /api/v1/salesPush sales. Body: {"records":[{"date":"2026-09-30","machine":"","amount":41.5,"units":23,"cash":10,"card":31.5,"product":"Coke Zero"}]}. Re-pushing the same day replaces the earlier API rows (idempotent). Up to 5000 records a call.
POST /api/v1/machinesCreate or update machines. Body: {"machines":[{"name":"Lobby snack","type":"snack","provider":"nayax","provider_machine_id":"...","serial":"...","location_name":"...","address":"..."}]}. A machine is matched by id, provider id or serial.
GET /api/v1/webhooksYour webhooks.
POST /api/v1/webhooksAdd one: {"url":"https://...","events":["lead.revealed","sale.recorded"]}. The response carries the signing secret once.
DELETE /api/v1/webhooks/:idRemove one.
POST /api/v1/webhooks/:id/testSend a webhook.test event now.
GET /api/v1/deliveriesYour last 50 webhook deliveries with status codes.

Webhooks

Events: lead.revealed, pipeline.updated, machine.updated, sale.recorded (or *). Each delivery is a JSON POST:

{
  "id": "evt_...",
  "event": "lead.revealed",
  "created_at": "2026-09-30T14:02:11.000Z",
  "data": { "org_name": "Acme Tool & Die", "name": "Dana Ortiz", "title": "Office Manager", "email": "[email protected]", "phone": "(703) 555-0100", "city": "Woodbridge", "state": "VA", "zip": "22191" }
}

Headers: X-VB-Event, X-VB-Delivery, and X-VB-Signature: t=<unix seconds>,v1=<hex> where v1 = HMAC-SHA256(secret, t + "." + body). Verify it before trusting a delivery:

const crypto = require('crypto');
function verify(secret, header, rawBody) {
  const m = /t=(\d+),v1=([0-9a-f]{64})/.exec(header);
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}

Answer 2xx within 8 seconds. Failures retry after 1 s, 10 s and 60 s; 20 failures in a row pause the webhook until you save it again.

Where the data comes from

Sales rows come from whatever you connect: a telemetry provider synced in the app (Nayax today), a CSV or DEX file you upload, or this API. Rows are keyed by day and machine and never double counted. Machines matched by provider_machine_id or serial pick up sales from a connected provider automatically.

Common uses

Questions: [email protected]