Core Resources API
Organizations, workspaces, and projects — the foundational hierarchy of ProBeya.
Core Resources API
ProBeya organizes data in a three-level hierarchy: Organization > Workspace > Project. This maps directly to how pharma companies structure operations: the organization is the tenant (e.g., Acme Pharma), workspaces are sites, departments, or areas (up to 3 levels deep), and projects are where boards, items, KPIs, and actions live.
Quick Start
Create a site workspace, add a quality department, then create a project — all in under 30 seconds:
Authentication
All endpoints require a valid Bearer token (API key) or session cookie. Organization context is resolved from the API key’s bound organization.
curl -H "Authorization: Bearer probeya_sk_live_7f3a..." \
https://acme.probeya.com/api/v1/organizations
Generate an API key from Settings > API Keys in the ProBeya web app. Each key is scoped to a specific organization and user.
Organizations
GET /api/v1/organizations
List all organizations the authenticated user is a member of.
tRPC: organizations.list | Scope: read:items | Org context: Not required
Response:
{
"data": [
{
"id": "clx9abc123def",
"name": "Acme Pharma",
"slug": "acme",
"plan": "pro",
"logo": "https://cdn.probeya.com/orgs/acme-logo.png",
"createdAt": "2026-01-15T10:00:00.000Z",
"role": "org_owner",
"roles": ["org_owner"]
},
{
"id": "clx9xyz789ghi",
"name": "Acme Biologics (EU)",
"slug": "acme-bio-eu",
"plan": "enterprise",
"logo": null,
"createdAt": "2026-03-01T08:00:00.000Z",
"role": "org_member",
"roles": ["org_member", "workspace_admin"]
}
]
}
Errors:
| Code | Description | Cause | Fix |
|---|---|---|---|
| 401 | UNAUTHORIZED | Missing or expired Bearer token | Regenerate your API key from Settings > API Keys |
| 500 | INTERNAL_SERVER_ERROR | Database connection failure | Retry after a brief delay; contact support if persistent |
Workspaces
Workspaces represent the physical or logical structure of your organization. They nest up to 3 levels deep following the pattern Site (L1) > Department (L2) > Area (L3).
GET /api/v1/workspaces
List all workspaces in the current organization. Returns a flat list with parentId and level fields for client-side tree rendering.
tRPC: workspaces.list | Scope: read:items | Org context: Required
Response:
{
"data": [
{
"id": "clx9ws001",
"name": "Brussels Manufacturing Site",
"slug": "brussels-site",
"level": 1,
"parentId": null,
"organizationId": "clx9abc123def",
"createdAt": "2026-01-20T08:00:00.000Z",
"updatedAt": "2026-01-20T08:00:00.000Z"
},
{
"id": "clx9ws002",
"name": "Quality Assurance",
"slug": "qa-dept",
"level": 2,
"parentId": "clx9ws001",
"organizationId": "clx9abc123def",
"createdAt": "2026-01-21T09:00:00.000Z",
"updatedAt": "2026-01-21T09:00:00.000Z"
},
{
"id": "clx9ws003",
"name": "Sterile Filling Area",
"slug": "sterile-filling",
"level": 3,
"parentId": "clx9ws002",
"organizationId": "clx9abc123def",
"createdAt": "2026-02-10T07:30:00.000Z",
"updatedAt": "2026-02-10T07:30:00.000Z"
}
]
}
tRPC-only: Use workspaces.getTree to get a pre-built nested tree structure instead of a flat list.
Errors:
| Code | Description | Cause | Fix |
|---|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid authentication | Check your Bearer token |
| 403 | FORBIDDEN | No organization context resolved | Ensure the API key is bound to an organization |
POST /api/v1/workspaces
Create a new workspace. Optionally nest it under a parent (max depth: 3 levels).
tRPC: workspaces.create | Scope: write:items | Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workspace display name |
slug | string | Yes | URL-safe slug (unique within org) |
parentId | string | No | Parent workspace ID for nesting (level auto-computed from parent) |
description | string | No | Optional description |
Response:
{
"data": {
"id": "clx9ws004",
"name": "Packaging Line 3",
"slug": "packaging-l3",
"level": 3,
"parentId": "clx9ws002",
"organizationId": "clx9abc123def",
"createdAt": "2026-04-13T12:00:00.000Z",
"updatedAt": "2026-04-13T12:00:00.000Z"
}
}
Errors:
| Code | Description | Cause | Fix |
|---|---|---|---|
| 400 | BAD_REQUEST | Max nesting depth exceeded (3 levels) | Move the workspace under a shallower parent |
| 400 | BAD_REQUEST | Slug already in use within this org | Choose a unique slug |
| 401 | UNAUTHORIZED | Missing or invalid authentication | Check your Bearer token |
| 403 | FORBIDDEN | Plan workspace limit reached | Upgrade your plan or delete unused workspaces |
| 404 | NOT_FOUND | Parent workspace not found in this org | Verify the parentId belongs to your organization |
Projects
GET /api/v1/projects
List projects within a workspace.
tRPC: projects.list | Scope: read:items | Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
workspaceId | string (query) | Yes | The workspace to list projects for |
Response:
{
"data": [
{
"id": "clx9pj001",
"name": "OEE Improvement Q2-2026",
"slug": "oee-q2-2026",
"workspaceId": "clx9ws001",
"organizationId": "clx9abc123def",
"createdAt": "2026-02-01T10:00:00.000Z",
"updatedAt": "2026-02-15T14:30:00.000Z"
},
{
"id": "clx9pj002",
"name": "CAPA Tracking",
"slug": "capa-tracking",
"workspaceId": "clx9ws001",
"organizationId": "clx9abc123def",
"createdAt": "2026-03-10T08:00:00.000Z",
"updatedAt": "2026-04-01T11:20:00.000Z"
}
]
}
POST /api/v1/projects
Create a new project. Automatically creates a default board with three groups (To Do, In Progress, Done) and four columns (Status, Person, Date, Priority).
tRPC: projects.create | Scope: write:items | Org context: Required
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project display name |
slug | string | Yes | URL-safe slug (unique within workspace) |
workspaceId | string | Yes | Parent workspace ID |
description | string | No | Optional description |
Response:
{
"data": {
"id": "clx9pj003",
"name": "Batch Release Tracker",
"slug": "batch-release-tracker",
"workspaceId": "clx9ws001",
"organizationId": "clx9abc123def",
"createdAt": "2026-04-13T12:05:00.000Z",
"updatedAt": "2026-04-13T12:05:00.000Z"
}
}
Errors:
| Code | Description | Cause | Fix |
|---|---|---|---|
| 400 | BAD_REQUEST | Invalid input (missing name or slug) | Provide all required fields |
| 401 | UNAUTHORIZED | Missing or invalid authentication | Check your Bearer token |
| 403 | FORBIDDEN | Plan board limit reached | Upgrade your plan or archive unused projects |
Pharma Integration Scenario
Rate Limiting
All core endpoints are subject to Redis-based sliding window rate limiting:
| Plan | Requests/min | Burst (10s window) |
|---|---|---|
| Free | 60 | 15 |
| Starter | 120 | 30 |
| Pro | 300 | 75 |
| Enterprise | 600 | 150 |
Rate limit headers are included on every response:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1711792800
When the limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header in seconds.
tRPC-Only Procedures
These procedures are available via the tRPC client but not exposed as REST endpoints:
| Procedure | Description |
|---|---|
workspaces.getTree | Get workspaces as a nested tree structure (with children arrays) |
workspaces.update | Update workspace name, slug, description, or reparent |
workspaces.delete | Delete a workspace (cascades to children and all contained projects) |
projects.update | Update project name, slug, or description |
projects.delete | Delete a project and its board (cascades to items, values, KPIs) |
organizations.getBySlug | Get organization details by slug (for subdomain resolution) |
Was this page helpful?