Catalio provides a comprehensive JSON:API implementation for programmatic access to all Documentation domain resources. This API follows the JSON:API v1.1 specification and provides standardized REST endpoints with powerful features like relationship inclusion, sparse fieldsets, filtering, sorting, and pagination.
Table of Contents
- What is JSON:API?
- API Resources
- Base URL & Endpoints
- Authentication
- Interactive Documentation
- Common Request Patterns
- Response Format
- Filtering, Sorting & Pagination
- Relationship Management
- Error Handling
- Multi-Tenant Architecture
- Rate Limiting
- Quick Start Examples
- Next Steps
What is JSON:API?
JSON:API is a specification for building APIs in JSON. It provides conventions for:
- Resource objects with
typeandid - Relationships between resources
- Included resources (eager loading)
- Sparse fieldsets (requesting specific fields)
- Filtering, sorting, and pagination
- Standardized error responses
Why JSON:API?
- Consistency: Predictable structure across all endpoints
- Efficiency: Reduce round trips with relationship inclusion
- Flexibility: Request exactly the data you need
- Developer Experience: Rich ecosystem of client libraries
- Documentation: Self-documenting via OpenAPI spec
API Resources
Catalio exposes the following resources via JSON:API:
| Resource | Type | Description | Endpoint |
|---|---|---|---|
| Requirement | requirement |
Business requirements, user stories, feature specifications | /api/v1/requirements |
| Persona | persona |
User personas, roles, stakeholders | /api/v1/personas |
| UseCase | use_case |
Use case scenarios with acceptance criteria | /api/v1/use_cases |
| TestCase | test_case |
Test specifications with steps and expected results | /api/v1/test_cases |
| TestResult | test_result |
Test execution records with outcomes | /api/v1/test_results |
| Component | component |
System components, modules, services | /api/v1/components |
| Process | process |
Business processes and workflows | /api/v1/processes |
Each resource supports standard CRUD operations:
- GET
/api/v1/{resource}- List all resources - GET
/api/v1/{resource}/:id- Get single resource - POST
/api/v1/{resource}- Create new resource - PATCH
/api/v1/{resource}/:id- Update resource - DELETE
/api/v1/{resource}/:id- Delete resource
Base URL & Endpoints
All API requests should be made to your Catalio instance’s API endpoint:
/api/v1
For example, if your Catalio instance is at https://app.catalio.com, use:
https://app.catalio.com/api/v1
Authentication
All JSON:API endpoints require authentication using Bearer tokens.
Request Headers
GET /api/v1/requirements HTTP/1.1
Authorization: Bearer YOUR_TOKEN_HERE
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
Required Headers
| Header | Value | Purpose |
|---|---|---|
Authorization |
Bearer {token} |
Authentication token |
Content-Type |
application/vnd.api+json |
Request body format (POST/PATCH) |
Accept |
application/vnd.api+json |
Response format |
See the Authentication API Guide for details on obtaining and managing tokens.
Interactive Documentation
OpenAPI Specification
The complete API specification is available in OpenAPI 3.0 format:
/api/v1/open_api
Download the spec to:
- Generate client libraries in any language
- Import into API testing tools (Postman, Insomnia)
- Validate requests and responses
- Auto-generate documentation
Swagger UI
Interactive API documentation with live testing is available at:
/api/swaggerui
The Swagger UI provides:
- Browse endpoints by resource type
- Try it out - Execute requests directly from the browser
- View schemas - Inspect request/response structures
- See examples - Reference example payloads
- Authentication - Test with your own Bearer token
Using Swagger UI:
- Navigate to
/api/swaggerui - Click “Authorize” button
- Enter your Bearer token:
Bearer YOUR_TOKEN_HERE - Browse resources by clicking on resource tags (Requirement, Persona, etc.)
- Expand operations (GET, POST, PATCH, DELETE)
- Click “Try it out” to execute requests
Common Request Patterns
Get All Resources
curl /api/v1/requirements \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.api+json"
Get Single Resource
curl /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6 \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.api+json"
Create Resource
curl -X POST /api/v1/requirements \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "requirement",
"attributes": {
"title": "OAuth2 Authentication",
"user_want": "authenticate using OAuth2",
"user_benefit": "secure passwordless access"
}
}
}'
Update Resource
curl -X PATCH /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6 \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "requirement",
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y6",
"attributes": {
"status": "active",
"priority": "high"
}
}
}'
Delete Resource
curl -X DELETE /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6 \
-H "Authorization: Bearer ${TOKEN}"
Response Format
Single Resource Response
{
"data": {
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y6",
"type": "requirement",
"attributes": {
"title": "OAuth2 Authentication",
"user_want": "authenticate using OAuth2",
"user_benefit": "secure passwordless access",
"status": "active",
"priority": "high",
"inserted_at": "2025-03-01T10:30:00.000000Z",
"updated_at": "2025-03-05T14:15:00.000000Z"
},
"relationships": {
"personas": {
"data": [{ "type": "persona", "id": "01JB2QE8V5X9R7M3P4N6K8W2Y2" }]
},
"created_by": {
"data": { "type": "user", "id": "01JB2QE8V5X9R7M3P4N6K8W2Y3" }
}
}
}
}
Collection Response
{
"data": [
{
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y6",
"type": "requirement",
"attributes": {
/* ... */
}
},
{
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y7",
"type": "requirement",
"attributes": {
/* ... */
}
}
],
"meta": {
"total_count": 142,
"page": 1,
"page_size": 25
},
"links": {
"self": "/api/v1/requirements?page[number]=1",
"next": "/api/v1/requirements?page[number]=2",
"last": "/api/v1/requirements?page[number]=6"
}
}
Filtering, Sorting & Pagination
Filtering
Use filter[field] query parameters to filter results:
# Filter by status
GET /api/v1/requirements?filter[status]=active
# Multiple filters
GET /api/v1/requirements?filter[status]=active&filter[priority]=high
# Filter by relationship
GET /api/v1/use_cases?filter[requirement_id]=01JB2QE8V5X9R7M3P4N6K8W2Y6
Sorting
Use sort parameter (prefix - for descending):
# Sort by title ascending
GET /api/v1/requirements?sort=title
# Sort by priority descending, then title ascending
GET /api/v1/requirements?sort=-priority,title
# Sort by most recently updated
GET /api/v1/requirements?sort=-updated_at
Pagination
Use page[number] and page[size] parameters:
# First page (25 results)
GET /api/v1/requirements?page[number]=1&page[size]=25
# Third page (50 results)
GET /api/v1/requirements?page[number]=3&page[size]=50
# Maximum page size (100 results)
GET /api/v1/requirements?page[size]=100
Combining Parameters
GET /api/v1/requirements?filter[status]=active&sort=-priority&page[size]=50&include=personas
Relationship Management
Including Relationships
Use include parameter to eager-load related resources:
# Include personas
GET /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6?include=personas
# Include multiple relationships
GET /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6?include=personas,created_by,use_cases
# Include nested relationships
GET /api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6?include=use_cases.test_cases
Response with Included Resources:
{
"data": {
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y6",
"type": "requirement",
"attributes": {
/* ... */
},
"relationships": {
"personas": {
"data": [{ "type": "persona", "id": "01JB2QE8V5X9R7M3P4N6K8W2Y2" }]
}
}
},
"included": [
{
"id": "01JB2QE8V5X9R7M3P4N6K8W2Y2",
"type": "persona",
"attributes": {
"name": "Product Manager",
"role": "Decision maker for product features"
}
}
]
}
Sparse Fieldsets
Request specific fields using fields[type] parameter:
# Only title and status for requirements
GET /api/v1/requirements?fields[requirement]=title,status,priority
# Specific fields for included resources
GET /api/v1/requirements?include=personas&fields[requirement]=title,status&fields[persona]=name
Error Handling
Error Response Format
{
"errors": [
{
"status": "422",
"code": "validation_error",
"title": "Validation Error",
"detail": "Title is required",
"source": {
"pointer": "/data/attributes/title"
}
}
]
}
Common HTTP Status Codes
| Status | Code | Description |
|---|---|---|
| 200 | OK | Successful GET/PATCH |
| 201 | Created | Successful POST |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Malformed request |
| 401 | Unauthorized | Missing/invalid authentication |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn’t exist |
| 422 | Unprocessable Entity | Validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
Multiple Validation Errors
{
"errors": [
{
"status": "422",
"code": "validation_error",
"detail": "Title is required",
"source": { "pointer": "/data/attributes/title" }
},
{
"status": "422",
"code": "validation_error",
"detail": "User want is required",
"source": { "pointer": "/data/attributes/user_want" }
}
]
}
Multi-Tenant Architecture
All JSON:API endpoints enforce strict organization-level data isolation:
- Automatic scoping: Queries are automatically scoped to your organization
- Actor context: Extracted from authentication token
- Tenant context: Organization ID from user’s context
- Cross-tenant prevention: Cannot access other organizations’ data
- 404 instead of 403: For security, returns “not found” instead of “forbidden” for cross-tenant access attempts
How Multi-Tenancy Works
- Authentication: Your Bearer token identifies you and your organization
- Authorization: All Ash actions enforce organization-level policies
- Queries: All reads filtered to your organization automatically
- Writes: All creates/updates tagged with your organization ID
- Relationships: Can only link resources within your organization
Security Guarantees
- No cross-tenant data leaks: Impossible to access other organizations’ data
- Audit trails: All changes tracked with actor (user) and tenant (org)
- Policy enforcement: Ash authorization policies on every action
- Resource isolation: Even shared infrastructure maintains logical separation
Rate Limiting
(Future implementation - currently not enforced)
Planned rate limits per organization:
| Operation Type | Limit | Window |
|---|---|---|
| Read operations | 1000 requests | 1 hour |
| Write operations | 100 requests | 1 hour |
| AI operations | 50 requests | 1 hour |
Rate limit headers (future):
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 842
X-RateLimit-Reset: 1699564200
Quick Start Examples
Python with requests
import requests
import os
# Configuration
API_BASE = os.getenv("CATALIO_API_BASE", "https://your-instance.catalio.com/api/v1")
TOKEN = os.getenv("CATALIO_API_TOKEN")
HEADERS = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/vnd.api+json",
"Accept": "application/vnd.api+json"
}
# List requirements
response = requests.get(f"{API_BASE}/requirements", headers=HEADERS)
requirements = response.json()["data"]
# Get single requirement with relationships
response = requests.get(
f"{API_BASE}/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6",
headers=HEADERS,
params={"include": "personas,use_cases"}
)
requirement = response.json()["data"]
# Create requirement
payload = {
"data": {
"type": "requirement",
"attributes": {
"title": "OAuth2 Authentication",
"user_want": "authenticate using OAuth2",
"user_benefit": "secure passwordless access"
}
}
}
response = requests.post(
f"{API_BASE}/requirements",
headers=HEADERS,
json=payload
)
created = response.json()["data"]
# Update requirement
update_payload = {
"data": {
"type": "requirement",
"id": created["id"],
"attributes": {
"status": "active",
"priority": "high"
}
}
}
response = requests.patch(
f"{API_BASE}/requirements/{created['id']}",
headers=HEADERS,
json=update_payload
)
JavaScript with fetch
const API_BASE = 'https://your-instance.catalio.com/api/v1'
const TOKEN = process.env.CATALIO_API_TOKEN || 'your_bearer_token_here'
const headers = {
Authorization: `Bearer ${TOKEN}`,
'Content-Type': 'application/vnd.api+json',
Accept: 'application/vnd.api+json',
}
// List requirements
const response = await fetch(`${API_BASE}/requirements`, { headers })
const { data: requirements } = await response.json()
// Get single requirement with relationships
const detailResponse = await fetch(
`${API_BASE}/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6?include=personas,use_cases`,
{ headers }
)
const { data: requirement } = await detailResponse.json()
// Create requirement
const createResponse = await fetch(`${API_BASE}/requirements`, {
method: 'POST',
headers,
body: JSON.stringify({
data: {
type: 'requirement',
attributes: {
title: 'OAuth2 Authentication',
user_want: 'authenticate using OAuth2',
user_benefit: 'secure passwordless access',
},
},
}),
})
const { data: created } = await createResponse.json()
// Update requirement
const updateResponse = await fetch(`${API_BASE}/requirements/${created.id}`, {
method: 'PATCH',
headers,
body: JSON.stringify({
data: {
type: 'requirement',
id: created.id,
attributes: {
status: 'active',
priority: 'high',
},
},
}),
})
cURL Examples
# List all requirements
curl /api/v1/requirements \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.api+json"
# Get requirement with relationships
curl "/api/v1/requirements/01JB2QE8V5X9R7M3P4N6K8W2Y6?include=personas,use_cases" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.api+json"
# Create requirement
curl -X POST /api/v1/requirements \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/vnd.api+json" \
-d '{
"data": {
"type": "requirement",
"attributes": {
"title": "OAuth2 Authentication",
"user_want": "authenticate using OAuth2",
"user_benefit": "secure passwordless access"
}
}
}'
# Filter active high-priority requirements
curl "/api/v1/requirements?filter[status]=active&filter[priority]=high&sort=-updated_at" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: application/vnd.api+json"
Next Steps
Resource-Specific Guides
- Requirements API - Complete CRUD operations, AI features, semantic search
- Personas API - User personas and stakeholder management
- Use Cases API - Scenarios and acceptance criteria
- Test Cases API - Test specifications and execution
- Components API - System components and architecture
- Processes API - Business processes and workflows
Additional Topics
- Authentication API - Token management and authentication
- Webhooks - Real-time event notifications
- GraphQL API - Flexible querying with GraphQL (coming soon)
- Best Practices - Patterns, performance, error handling
Interactive Resources
- OpenAPI Spec:
/api/v1/open_api - Swagger UI:
/api/swaggerui
Ready to build? Start with the Swagger UI to explore endpoints interactively, then dive into resource-specific guides for detailed examples.