Buddy Punch

Getting Started

Welcome to the Buddy Punch Public API. This guide takes you from zero to your first authenticated request in about ten minutes, then shows you how to paginate, handle rate limits, and parse errors.

Pin a version header (X-Api-Version: 2025-03-01) so your integration keeps working when newer versions ship, and watch the Changelog for breaking changes.

If you're migrating an existing integration from the legacy api.buddypunch.com endpoints, read the Migration Guide after this.


1. Create an API Key

  1. Log in to Buddy Punch
  2. Navigate to Settings → Integrations → Developer API → Manage API Keys
  3. Click Create API Key
  4. Select the permission scopes your integration needs (for example employees:read, locations:write)
  5. Copy the key. Production keys start with bp_live_.

Store your key securely. It cannot be retrieved after creation. If it leaks, revoke it and create a new one.


2. Make Your First Request

Every request sends the key as a Bearer token:

curl https://api2.buddypunch.com/employee \
  -H "Authorization: Bearer bp_live_xxxxxxxxxxxxxxxx"

On success you get a 200 OK with a paginated list envelope:

{
  "object": "list",
  "data": [
    {
      "id": 4521,
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane.smith@example.com",
      "isActive": true
    }
  ],
  "hasMore": false,
  "totalCount": 1,
  "url": "/employee"
}

If your key is missing or invalid you get 401 Unauthorized; if the key lacks the required scope you get 403 Forbidden. See the Errors guide for the full catalog.


3. Understanding the Response Envelope

Every list endpoint wraps results in a consistent envelope:

Field Type Description
object string Always "list" for list responses
data array The items for this page
hasMore boolean true if more items are available
totalCount integer Number of items returned, or total known items, depending on the endpoint
url string The endpoint path that produced this response

Single-resource responses (like GET /employee/{id}) return the resource object directly without a wrapper.


4. Pagination

List endpoints use cursor-based pagination. Pass limit to control page size (1–100, default 25) and startingAfter to request the next page using the last item's id:

# First page
curl "https://api2.buddypunch.com/employee?limit=50" \
  -H "Authorization: Bearer bp_live_xxxxxxxxxxxxxxxx"

# Next page — pass the id of the last item from the previous page
curl "https://api2.buddypunch.com/employee?limit=50&startingAfter=4572" \
  -H "Authorization: Bearer bp_live_xxxxxxxxxxxxxxxx"

Loop until hasMore is false. Cursor-based pagination means page boundaries stay stable even while new items are being created.


5. Rate Limits

Requests are limited per account using a sliding-window counter. The per-minute ceiling depends on your Buddy Punch plan:

Plan tier Per-account limit
Trial / non-paying 60 requests/minute
Pro / Premium / Starter (any paid non-Enterprise) 600 requests/minute
Enterprise 1,000 requests/minute

A separate per-API-key DoS guard of 1,000 requests/minute runs alongside the per-account limit to protect the platform — well-behaved integrations rarely hit it.

On a 429 Too Many Requests response the API tells you which limit you hit and when to retry. Two flavors of 429 exist with slightly different headers:

Per-minute rate-limit 429s (error.code = rate_limit_exceeded or account_rate_limit_exceeded):

Header Description
X-RateLimit-Limit Maximum requests per window for the limit you tripped
X-RateLimit-Remaining Always 0 on a 429 — you're exactly at the limit
Retry-After Number of seconds to wait before retrying

Trial-only 429s (error.code = trial_resource_limit_exceeded, trial_resource_daily_limit_exceeded, or trial_daily_writes_exceeded):

Header Description
Retry-After Conservative seconds to wait (resource-ceiling rejections aren't really retryable — the cap won't drop until you delete a resource or upgrade)

X-RateLimit-* headers are not set on trial-only 429s because the trial caps are volume/count limits, not per-minute rates. Branch on error.code to tell them apart.

On any 429, sleep for Retry-After seconds and try again. Back off exponentially on repeated failures. Successful responses do not currently include these headers — check for 429 status explicitly rather than looking at X-RateLimit-Remaining on every request.

Trial accounts also have a few additional safeguards (smaller per-resource caps, daily write caps, and a one-active-API-key limit enforced in the dashboard) — see the Errors guide for the codes you may encounter.


6. Error Handling

All errors return the same envelope shape:

{
  "error": {
    "type": "invalid_request_error",
    "code": "resource_not_found",
    "message": "Employee 999 not found.",
    "requestId": "req_abc123"
  }
}

The Errors guide lists every (type, code) pair the API emits along with retry recommendations.


7. Common Pitfalls


8. Next Steps

Guide When to read
Data Model You're building a UI and need the field shape of every resource
Errors You want the full error catalog and retry strategy
Idempotency You're making write requests and need safe retries
Code Examples You want copy-paste samples in curl / Node.js / Python / C#
Webhooks You want real-time event notifications instead of polling
Migration Guide You're moving from the legacy API

The interactive API reference has "Try It" consoles for every endpoint once you paste your key.