Puchify

Core Concepts

Understanding the Puchify object model, resource lifecycle, and API design.

Resources

Everything in Puchify is a resource. Servers, databases, Kubernetes clusters, load balancers — all resources follow the same lifecycle and share a consistent API.

Resource lifecycle

Created ──► Creating ──► Running ──► Stopped ──► Destroyed
                     \              /
                      └──► Failed ◄┘

States are lowercase identifiers returned by the API:

  • creating — provisioning in progress
  • running (or healthy / available) — resource is operational
  • stopped — resource exists but is powered off
  • deleted — soft-deleted, still visible in history
  • destroyed — resource is gone, provider resources released
  • failed — provisioning error

CRUD + Actions

Every resource supports the standard CRUD operations plus resource-specific actions:

OperationMethodExample
ListGET /api/v1/{resource}GET /api/v1/servers
CreatePOST /api/v1/{resource}POST /api/v1/servers
GetGET /api/v1/{resource}/{id}GET /api/v1/servers/svr_123
UpdatePATCH /api/v1/{resource}/{id}PATCH /api/v1/servers/svr_123
DeleteDELETE /api/v1/{resource}/{id}DELETE /api/v1/servers/svr_123
ActionPOST /api/v1/{resource}/{id}/{action}POST /api/v1/servers/svr_123/restart

Response envelope

Every API response follows a consistent format:

{
  "data": { ... },
  "meta": {
    "persistence": "synced",
    "provider": "connected",
    "next_cursor": null
  }
}
  • data — the resource or resource list
  • meta.persistencesynced (DB confirmed), stale (cache), unavailable
  • meta.providerconnected, degraded, or unavailable (cloud provider status)
  • meta.next_cursor — for paginated list responses

Error responses:

{
  "error": {
    "code": "server_not_found",
    "message": "Server svr_abc123 not found"
  },
  "meta": {
    "persistence": "synced",
    "provider": "connected"
  }
}

Pagination

List endpoints use cursor-based pagination:

// GET /api/v1/servers?limit=10
{
  "data": [ ... ],
  "meta": {
    "next_cursor": "cursor_abc123",
    // ...
  }
}

// GET /api/v1/servers?cursor=cursor_abc123&limit=10
{
  "data": [ ... ],
  "meta": {
    "next_cursor": null  // last page
  }
}

Authentication

Two authentication methods:

API keys (recommended for programmatic access):

Authorization: Bearer pk_xxxx

Create and manage API keys in Settings → API Keys. Keys are bcrypt-hashed at rest; only the prefix and the full key (shown once at creation) can access the API.

Session cookies — used automatically by the web app via WorkOS AuthKit.

Rate limiting

API keys are rate-limited to 1000 requests per minute. Rate limit headers are included in every response:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1680000000

Exceeding the limit returns 429 Too Many Requests.

Event-driven architecture

Resource state changes emit events. These events power:

  • Webhooks — outbound HTTP POST to your endpoints
  • Audit log — searchable event history
  • Agent — the AI agent reacts to events

Events are fire-and-forget with best-effort delivery. Webhooks include HMAC-SHA256 signatures for verification.

On this page