API Guides

JSON:API Overview & Getting Started

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

  1. What is JSON:API?
  2. API Resources
  3. Base URL & Endpoints
  4. Authentication
  5. Interactive Documentation
  6. Common Request Patterns
  7. Response Format
  8. Filtering, Sorting & Pagination
  9. Relationship Management
  10. Error Handling
  11. Multi-Tenant Architecture
  12. Rate Limiting
  13. Quick Start Examples
  14. Next Steps

What is JSON:API?

JSON:API is a specification for building APIs in JSON. It provides conventions for:

  • Resource objects with type and id
  • 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:

  1. Navigate to /api/swaggerui
  2. Click “Authorize” button
  3. Enter your Bearer token: Bearer YOUR_TOKEN_HERE
  4. Browse resources by clicking on resource tags (Requirement, Persona, etc.)
  5. Expand operations (GET, POST, PATCH, DELETE)
  6. 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

  1. Authentication: Your Bearer token identifies you and your organization
  2. Authorization: All Ash actions enforce organization-level policies
  3. Queries: All reads filtered to your organization automatically
  4. Writes: All creates/updates tagged with your organization ID
  5. 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

Additional Topics

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.