Operations

API and webhooks

BadgeBadger has a small HTTP API for syncing employee records and printing badges, and a webhook stream for downstream systems.

Create an API token

  1. Open Settings → API tokens.
  2. Type a name for the token (e.g. “SIS sync”). Leave Allow printing off unless the integration prints badges. Click Create, and copy the token. It’s shown once, so store it in your secrets manager.
  3. Tokens are scoped to your organization. Revoking a token from the same page invalidates it immediately.

Endpoints

All endpoints accept Authorization: Bearer <token> and return JSON. See the full reference at Settings → API tokens → View docs (signed-in admins only).

  • GET /api/v1/employees: list all your employees.
  • POST /api/v1/employees: create or update up to 1,000 employees per request, matched on employee_id. Fields you leave out keep their current values.
  • GET /api/v1/templates: list your templates (name, card size, and whether each one is two-sided).
  • GET /api/v1/print-jobs: list recent print history, newest first, from the app and the API.
  • GET /api/v1/printers: your paired print computers, their printers, and which computers are online.
  • POST /api/v1/print-jobs: print badges for up to 25 people. See Printing below.
  • GET /api/v1/print-jobs/{id}: the status of a print you started.

Employee rows include a photo_id, not the photo itself. The API doesn’t return photo files or rendered badges.

The same endpoints are described in OpenAPI 3.1 at /api/v1/openapi.json, which anyone can read without a token. To let an AI agent use them, see Connect AI agents (MCP).

Printing

POST /api/v1/print-jobs takes employee_ids (your own IDs, one card each) and prints them on a card printer attached to a paired computer that shares its printers. It works the way printing in the app does: the same pre-flight check, the same print approval, the same free trial count, and the same webhooks.

  • Off unless allowed. Only a token created with Allow printing can print; any other gets a 403. An admin can turn printing off for a token later. Turning it off, or revoking the token, cancels its prints that haven’t started, and each print checks the token again just before it goes to the printer.
  • Limits. 25 cards per request, and per organization 200 cards in any hour and 1,000 in any 24 hours through the API. Over a limit, the request gets a 429 with retry_after_seconds. Prints are prepared 2 at a time per organization; one more sent meanwhile gets a 429 with code busy, so wait a few seconds. The free trial stops at 10 printed cards (a 402).
  • Which printer. Send printer with a device_id and name from GET /api/v1/printers. You can leave it out when exactly one print computer is online. A computer that’s offline is refused, so prints don’t pile up and all come out when it’s next turned on.
  • Pre-flight. A card with a problem that blocks it refuses the whole request with a 422 that lists the problems. Warnings do too, unless you send acknowledge_warnings: true. The API also won’t print a badge for a terminated person.
  • Approval. If your organization requires print approval, the job waits as awaiting_approval until an admin approves every card, then prints. A rejected card ends it. Admins get an email when API prints start waiting, not one for every request. If the print computer is offline when the last card is approved, the job fails and the cards stay approved, so sending it again prints without asking again.
  • Retries. Send an idempotency_key. The same key within 24 hours returns the first job instead of printing again. If that job failed before it reached the printer, the key is free again, so the same request tries again.

A new job answers 202 with its id and a status of queued or awaiting_approval. Follow it with GET /api/v1/print-jobs/{id} until it’s printed, or failed, rejected or cancelled with an error saying why.

Every API print is in the audit log, and your admins get a notification in the app naming the token, the number of cards and the printer, so a token printing what it shouldn’t is noticed quickly.

Webhooks

From Settings → Webhooks, register HTTPS URLs to receive events:

  • badge.printed: every printed card, whether it came from an employee’s Print button, a bulk print, the kiosk, or the API. Carries the badge, employee, template, and operator IDs (no operator for an API print).
  • badge.created: the first time an employee’s badge prints on a template.
  • print_job.created: once per print run, with the badge IDs and the number of cards in it.
  • employee.created, employee.updated, employee.terminated: when employees are added, edited, or terminated, by hand, through a CSV import, or through the API. Each carries the employee’s internal ID and their employee number.

Deliveries are sent once, with a five-second timeout, and aren’t retried automatically. Each endpoint’s recent deliveries show the result, and you can replay any of them.

Every delivery includes an x-badgebadger-signature: sha256=<hex> header: an HMAC-SHA256 of the raw request body, keyed with the endpoint’s signing secret (BadgeBadger generates it when you create the webhook). Verify it before trusting the payload. It’s the same scheme GitHub uses for its webhooks. The full reference has example code.

Replay + rotate

The webhooks tester at Settings → Webhooks → Recent deliveries lets you replay any past delivery (handy when a receiver was down) and rotate the signing secret on demand.