Skip to main content
Manage bookkeeper organizations (the top-level tenant in PayPunch). All endpoints require an admin JWT (Authorization: Bearer <token>).
MethodPathPurpose
GET/api/v1/admin/bookkeeper-orgsList organizations (paginated)
POST/api/v1/admin/bookkeeper-orgsCreate an organization
GET/api/v1/admin/bookkeeper-orgs/{id}Get one organization
PUT/api/v1/admin/bookkeeper-orgs/{id}Update an organization
DELETE/api/v1/admin/bookkeeper-orgs/{id}Deactivate (soft delete)

List organizations

GET /api/v1/admin/bookkeeper-orgs

Query parameters

page
integer
default:"1"
Page number (1-based).
pageSize
integer
default:"20"
Number of results per page.
Case-insensitive match against name, slug, and email.
active
string
Pass true to return only active organizations. Any other value returns all.

Response

data
object
Paginated envelope: items, total, page, pageSize, totalPages. Each item includes a _count of related companies and adminUsers.
curl "https://app.paypunch.io/api/v1/admin/bookkeeper-orgs?page=1&pageSize=20&active=true" \
  -H "Authorization: Bearer <admin-token>"

Create an organization

POST /api/v1/admin/bookkeeper-orgs

Request body

name
string
required
Organization name.
slug
string
URL slug. If omitted, generated from name. Must be unique.
email
string
Contact email (validated as an email when present).
phone
string
address
string
city
string
state
string
zipCode
string
country
string
default:"USA"
timezone
string
default:"America/New_York"
dateFormat
string
default:"MM/DD/YYYY"
overtimeThreshold
number
default:"40"
Weekly hours before overtime applies. Minimum 0.
overtimeMultiplier
number
default:"1.5"
Overtime pay multiplier. Minimum 1.
Returns 201 with the created organization (and _count). Returns 400 Slug already exists if the slug collides.
curl -X POST https://app.paypunch.io/api/v1/admin/bookkeeper-orgs \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Bookkeeping",
    "email": "billing@acmebookkeeping.com",
    "timezone": "America/Chicago",
    "overtimeThreshold": 40,
    "overtimeMultiplier": 1.5
  }'

Get an organization

GET /api/v1/admin/bookkeeper-orgs/{id}
id
string
required
The organization’s UUID.
Returns the organization including its companies (with employee counts) and adminUsers. Returns 404 if not found.
Response (200)
{
  "success": true,
  "data": {
    "id": "a1c2...",
    "name": "Acme Bookkeeping",
    "companies": [
      { "id": "c9d8...", "name": "Builders R Us", "active": true, "_count": { "employees": 12 } }
    ],
    "adminUsers": [
      { "id": "0b6f...", "firstName": "Sarah", "lastName": "Lee", "email": "sarah@acmebookkeeping.com", "role": "SUPER_ADMIN", "active": true }
    ]
  }
}

Update an organization

PUT /api/v1/admin/bookkeeper-orgs/{id}
id
string
required
The organization’s UUID.
All body fields are optional; only provided fields are updated.
name
string
email
string
phone
string
address
string
city
string
state
string
zipCode
string
country
string
timezone
string
dateFormat
string
overtimeThreshold
number
Minimum 0.
overtimeMultiplier
number
Minimum 1.
active
boolean
Set false to deactivate or true to reactivate.
Returns 200 with the updated organization, or 404 if not found.

Deactivate an organization

DELETE /api/v1/admin/bookkeeper-orgs/{id}
id
string
required
The organization’s UUID.
This is a soft delete — it sets active = false and returns the updated record. Returns 404 if not found.
Response (200)
{
  "success": true,
  "data": { "id": "a1c2...", "active": false },
  "message": "Bookkeeper organization deactivated successfully"
}
These handlers call requireAuth(request, 'admin'), so a valid admin token is required. The source comments mark create as “super admin only” but the handlers do not enforce a specific admin role beyond the admin token type.