Task: Write API documentation with interactive examples for Enterprise Coolify
Description
Create comprehensive, production-ready API documentation for the Coolify Enterprise Transformation project. This documentation covers all new enterprise endpoints (organizations, white-label branding, Terraform infrastructure, resource monitoring, payment processing, domain management) with interactive examples, authentication guides, and complete code samples for multiple programming languages.
Why This Task is Critical:
API documentation is the primary interface between the platform and third-party developers, integration partners, and automation scripts. Without comprehensive, accurate documentation, enterprise customers cannot effectively:
Integrate Coolify into their existing workflows
Automate infrastructure provisioning and deployment
Build custom applications on top of Coolify's API
Troubleshoot integration issues
Understand authentication, authorization, and rate limiting
Professional API documentation transforms the platform from "possible to integrate" to "easy to integrate," directly impacting customer satisfaction, time-to-value, and platform adoption rates. Interactive examples allow developers to test API calls directly from the browser, reducing integration time from days to hours.
What Makes This Documentation Unique:
Unlike standard Coolify API docs, this enterprise documentation includes:
Organization-Scoped Authentication : All endpoints require organization context with Sanctum tokens
Tiered Rate Limiting : Different rate limits based on enterprise license tier (Starter, Professional, Enterprise)
Multi-Tenant Considerations : How to prevent cross-organization data leakage
Webhook Integrations : Payment gateway webhooks, Terraform provisioning status updates
Complex Workflows : Multi-step processes like provisioning infrastructure → deploying applications → configuring domains
Real-World Examples : Practical integration scenarios with error handling and retry logic
Integration Architecture:
The API documentation integrates with several existing and new systems:
Task 61 (Enhanced API System) : Documents all new API endpoints created in that task
Task 54 (Rate Limiting) : Explains tier-based rate limits and how to handle 429 responses
Task 52 (Sanctum Extensions) : Documents organization-scoped token authentication
Task 58 (Swagger UI) : Interactive API explorer embedded in documentation
Task 57 (OpenAPI Spec) : Auto-generated API reference from OpenAPI schema
Scope of Documentation:
Core Enterprise APIs (15+ endpoints):
Organization CRUD operations
Organization hierarchy management (parent/child relationships)
User-organization role assignments
White-label branding configuration
Terraform infrastructure provisioning
Resource monitoring and capacity planning
Payment and subscription management
Domain and DNS management
Authentication & Authorization (3 chapters):
Sanctum token generation with organization context
API key management with scoped abilities
Role-based access control (RBAC) for API operations
Advanced Topics (5 chapters):
Pagination strategies for large datasets
WebSocket subscriptions for real-time updates
Webhook configuration and HMAC validation
Error handling and retry strategies
Rate limit management and optimization
Interactive Examples (Swagger UI):
Try-it-out functionality for all endpoints
Pre-filled example requests
Response schema validation
Authentication token management
Output Deliverables:
OpenAPI 3.1 Specification : /docs/api/openapi.json (auto-generated, enhanced with examples)
Markdown Documentation : /docs/api/*.md (human-readable guides and tutorials)
Swagger UI : /api/documentation route (interactive API explorer)
Code Samples : /docs/api/examples/{language}/*.{ext} (PHP, JavaScript, Python, cURL)
Postman Collection : /docs/api/Coolify-Enterprise.postman_collection.json
Migration Guide : /docs/api/migration-from-standard-coolify.md
Acceptance Criteria
OpenAPI 3.1 specification enhanced with detailed descriptions, examples, and response schemas for all 15+ enterprise endpoints
Authentication guide with step-by-step Sanctum token generation (including organization context)
Rate limiting documentation explaining all three tiers (Starter: 100/min, Professional: 500/min, Enterprise: 2000/min)
Interactive Swagger UI deployed at /api/documentation route with working "Try it out" functionality
Code examples in 4 languages (PHP, JavaScript/Node.js, Python, cURL) for all major endpoints
Webhook integration guide with HMAC signature validation examples
Pagination guide with cursor-based and offset-based strategies
Error handling reference with all HTTP status codes (400, 401, 403, 404, 422, 429, 500, 503)
Migration guide from standard Coolify API to enterprise API
Postman collection exported and tested with all endpoints
Real-world workflow examples (provision infrastructure → deploy app → configure domain)
Security best practices section (token rotation, IP allowlisting, webhook validation)
API versioning strategy documented (current: v1, future compatibility guarantees)
Changelog maintained for API updates
Search functionality in documentation site
Dark mode support in documentation UI
Mobile-responsive documentation layout
Copy-to-clipboard buttons for all code samples
Documentation versioned and accessible for all API versions
All links in documentation verified and working
Technical Details
File Paths
Documentation Files:
/home/topgun/topgun/docs/api/README.md (new - main API documentation landing page)
/home/topgun/topgun/docs/api/authentication.md (new - Sanctum token guide)
/home/topgun/topgun/docs/api/rate-limiting.md (new - rate limit guide)
/home/topgun/topgun/docs/api/organizations.md (new - organization API reference)
/home/topgun/topgun/docs/api/white-label.md (new - branding API reference)
/home/topgun/topgun/docs/api/infrastructure.md (new - Terraform API reference)
/home/topgun/topgun/docs/api/monitoring.md (new - resource monitoring API reference)
/home/topgun/topgun/docs/api/payments.md (new - payment API reference)
/home/topgun/topgun/docs/api/domains.md (new - domain management API reference)
/home/topgun/topgun/docs/api/webhooks.md (new - webhook integration guide)
/home/topgun/topgun/docs/api/errors.md (new - error reference)
/home/topgun/topgun/docs/api/pagination.md (new - pagination strategies)
/home/topgun/topgun/docs/api/migration.md (new - migration guide)
/home/topgun/topgun/docs/api/changelog.md (new - API changelog)
Code Example Files:
/home/topgun/topgun/docs/api/examples/php/*.php (new - Laravel/Guzzle examples)
/home/topgun/topgun/docs/api/examples/javascript/*.js (new - Node.js/Axios examples)
/home/topgun/topgun/docs/api/examples/python/*.py (new - Requests library examples)
/home/topgun/topgun/docs/api/examples/curl/*.sh (new - cURL examples)
OpenAPI Specification:
/home/topgun/topgun/storage/api-docs/openapi.json (enhanced - auto-generated with custom annotations)
Swagger UI Integration:
/home/topgun/topgun/resources/views/api/documentation.blade.php (new - Swagger UI view)
/home/topgun/topgun/routes/web.php (modify - add /api/documentation route)
Postman Collection:
/home/topgun/topgun/docs/api/Coolify-Enterprise.postman_collection.json (new - exported collection)
OpenAPI Specification Enhancement
File: storage/api-docs/openapi.json (enhanced with custom annotations)
The existing OpenAPI spec (generated by L5-Swagger or similar) needs enhancement with:
{
"openapi" : " 3.1.0" ,
"info" : {
"title" : " Coolify Enterprise API" ,
"description" : " Comprehensive API for multi-tenant infrastructure provisioning, application deployment, and white-label branding. Supports organization hierarchies, tiered rate limiting, and real-time resource monitoring." ,
"version" : " 1.0.0" ,
"contact" : {
"name" : " Coolify Enterprise Support" ,
"email" : " enterprise@coolify.io" ,
"url" : " https://enterprise.coolify.io/support"
},
"license" : {
"name" : " Proprietary" ,
"url" : " https://enterprise.coolify.io/license"
}
},
"servers" : [
{
"url" : " https://api.coolify.io/v1" ,
"description" : " Production API"
},
{
"url" : " https://staging-api.coolify.io/v1" ,
"description" : " Staging API"
},
{
"url" : " http://localhost:8000/api/v1" ,
"description" : " Local Development"
}
],
"security" : [
{
"sanctum" : [" organization:read" , " organization:write" ]
}
],
"components" : {
"securitySchemes" : {
"sanctum" : {
"type" : " http" ,
"scheme" : " bearer" ,
"bearerFormat" : " Sanctum Token" ,
"description" : " Use a Sanctum personal access token with organization-scoped abilities. Generate tokens via POST /api/v1/auth/tokens with organization_id and abilities array."
}
},
"schemas" : {
"Organization" : {
"type" : " object" ,
"properties" : {
"id" : {"type" : " integer" , "example" : 42 },
"name" : {"type" : " string" , "example" : " Acme Corporation" },
"slug" : {"type" : " string" , "example" : " acme-corp" },
"type" : {
"type" : " string" ,
"enum" : [" top_branch" , " master_branch" , " sub_user" , " end_user" ],
"example" : " master_branch"
},
"parent_id" : {"type" : " integer" , "nullable" : true , "example" : 1 },
"created_at" : {"type" : " string" , "format" : " date-time" },
"updated_at" : {"type" : " string" , "format" : " date-time" }
},
"required" : [" id" , " name" , " slug" , " type" ]
},
"WhiteLabelConfig" : {
"type" : " object" ,
"properties" : {
"id" : {"type" : " integer" },
"organization_id" : {"type" : " integer" },
"platform_name" : {"type" : " string" , "example" : " Acme Cloud Platform" },
"primary_color" : {"type" : " string" , "pattern" : " ^#[0-9A-F]{6}$" , "example" : " #3B82F6" },
"secondary_color" : {"type" : " string" , "pattern" : " ^#[0-9A-F]{6}$" , "example" : " #8B5CF6" },
"accent_color" : {"type" : " string" , "pattern" : " ^#[0-9A-F]{6}$" , "example" : " #10B981" },
"logo_url" : {"type" : " string" , "format" : " uri" , "example" : " https://storage.coolify.io/branding/42/logo.png" },
"favicon_url" : {"type" : " string" , "format" : " uri" , "nullable" : true },
"custom_css" : {"type" : " string" , "nullable" : true }
}
},
"TerraformDeployment" : {
"type" : " object" ,
"properties" : {
"id" : {"type" : " integer" },
"organization_id" : {"type" : " integer" },
"provider" : {"type" : " string" , "enum" : [" aws" , " digitalocean" , " hetzner" , " gcp" , " azure" ]},
"status" : {"type" : " string" , "enum" : [" pending" , " planning" , " applying" , " completed" , " failed" , " destroying" ]},
"instance_count" : {"type" : " integer" , "example" : 3 },
"instance_type" : {"type" : " string" , "example" : " t3.medium" },
"region" : {"type" : " string" , "example" : " us-east-1" },
"terraform_output" : {"type" : " object" , "description" : " Parsed Terraform output with server IPs and IDs" }
}
},
"Error" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " The given data was invalid." },
"errors" : {
"type" : " object" ,
"additionalProperties" : {
"type" : " array" ,
"items" : {"type" : " string" }
},
"example" : {
"name" : [" The name field is required." ],
"email" : [" The email must be a valid email address." ]
}
}
}
},
"RateLimitHeaders" : {
"type" : " object" ,
"properties" : {
"X-RateLimit-Limit" : {"type" : " integer" , "description" : " Maximum requests allowed per window" , "example" : 500 },
"X-RateLimit-Remaining" : {"type" : " integer" , "description" : " Requests remaining in current window" , "example" : 487 },
"X-RateLimit-Reset" : {"type" : " integer" , "description" : " Unix timestamp when rate limit resets" , "example" : 1678901234 },
"Retry-After" : {"type" : " integer" , "description" : " Seconds to wait before retrying (only on 429)" , "example" : 42 }
}
}
},
"responses" : {
"Unauthorized" : {
"description" : " Authentication token is missing or invalid" ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " Unauthenticated." }
}
}
}
}
},
"Forbidden" : {
"description" : " Authenticated but lacking required permissions" ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " This action is unauthorized." }
}
}
}
}
},
"NotFound" : {
"description" : " Resource not found or not accessible in your organization" ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " Resource not found." }
}
}
}
}
},
"ValidationError" : {
"description" : " Request validation failed" ,
"content" : {
"application/json" : {
"schema" : {"$ref" : " #/components/schemas/Error" }
}
}
},
"RateLimitExceeded" : {
"description" : " Rate limit exceeded for your tier" ,
"headers" : {
"X-RateLimit-Limit" : {"schema" : {"type" : " integer" }},
"X-RateLimit-Remaining" : {"schema" : {"type" : " integer" }},
"X-RateLimit-Reset" : {"schema" : {"type" : " integer" }},
"Retry-After" : {"schema" : {"type" : " integer" }}
},
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " Too Many Requests" }
}
}
}
}
}
}
},
"paths" : {
"/organizations" : {
"get" : {
"summary" : " List all organizations accessible to the authenticated user" ,
"description" : " Returns a paginated list of organizations where the user has any role. Includes organization hierarchy information (parent/child relationships). Results are automatically scoped to the user's access." ,
"operationId" : " listOrganizations" ,
"tags" : [" Organizations" ],
"security" : [{"sanctum" : [" organization:read" ]}],
"parameters" : [
{
"name" : " page" ,
"in" : " query" ,
"description" : " Page number for pagination (1-indexed)" ,
"schema" : {"type" : " integer" , "default" : 1 , "minimum" : 1 }
},
{
"name" : " per_page" ,
"in" : " query" ,
"description" : " Number of results per page" ,
"schema" : {"type" : " integer" , "default" : 15 , "minimum" : 1 , "maximum" : 100 }
},
{
"name" : " type" ,
"in" : " query" ,
"description" : " Filter by organization type" ,
"schema" : {
"type" : " string" ,
"enum" : [" top_branch" , " master_branch" , " sub_user" , " end_user" ]
}
}
],
"responses" : {
"200" : {
"description" : " Successful response with paginated organizations" ,
"headers" : {
"X-RateLimit-Limit" : {"schema" : {"type" : " integer" }},
"X-RateLimit-Remaining" : {"schema" : {"type" : " integer" }},
"X-RateLimit-Reset" : {"schema" : {"type" : " integer" }}
},
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"data" : {
"type" : " array" ,
"items" : {"$ref" : " #/components/schemas/Organization" }
},
"meta" : {
"type" : " object" ,
"properties" : {
"current_page" : {"type" : " integer" , "example" : 1 },
"per_page" : {"type" : " integer" , "example" : 15 },
"total" : {"type" : " integer" , "example" : 47 },
"last_page" : {"type" : " integer" , "example" : 4 }
}
},
"links" : {
"type" : " object" ,
"properties" : {
"first" : {"type" : " string" , "format" : " uri" },
"last" : {"type" : " string" , "format" : " uri" },
"prev" : {"type" : " string" , "format" : " uri" , "nullable" : true },
"next" : {"type" : " string" , "format" : " uri" , "nullable" : true }
}
}
}
},
"examples" : {
"success" : {
"summary" : " Successful response" ,
"value" : {
"data" : [
{
"id" : 42 ,
"name" : " Acme Corporation" ,
"slug" : " acme-corp" ,
"type" : " master_branch" ,
"parent_id" : 1 ,
"created_at" : " 2024-01-15T10:30:00Z" ,
"updated_at" : " 2024-03-20T14:22:00Z"
}
],
"meta" : {
"current_page" : 1 ,
"per_page" : 15 ,
"total" : 47 ,
"last_page" : 4
},
"links" : {
"first" : " https://api.coolify.io/v1/organizations?page=1" ,
"last" : " https://api.coolify.io/v1/organizations?page=4" ,
"prev" : null ,
"next" : " https://api.coolify.io/v1/organizations?page=2"
}
}
}
}
}
}
},
"401" : {"$ref" : " #/components/responses/Unauthorized" },
"429" : {"$ref" : " #/components/responses/RateLimitExceeded" }
}
},
"post" : {
"summary" : " Create a new organization" ,
"description" : " Creates a new organization under the authenticated user's current organization (if hierarchical structure). Requires 'organization:write' ability." ,
"operationId" : " createOrganization" ,
"tags" : [" Organizations" ],
"security" : [{"sanctum" : [" organization:write" ]}],
"requestBody" : {
"required" : true ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"name" : {"type" : " string" , "minLength" : 1 , "maxLength" : 255 , "example" : " New Organization" },
"slug" : {"type" : " string" , "pattern" : " ^[a-z0-9-]+$" , "example" : " new-org" },
"type" : {
"type" : " string" ,
"enum" : [" top_branch" , " master_branch" , " sub_user" , " end_user" ],
"example" : " master_branch"
},
"parent_id" : {"type" : " integer" , "nullable" : true , "example" : 1 }
},
"required" : [" name" , " type" ]
},
"examples" : {
"master_branch" : {
"summary" : " Create master branch organization" ,
"value" : {
"name" : " Acme Corporation" ,
"slug" : " acme-corp" ,
"type" : " master_branch" ,
"parent_id" : 1
}
}
}
}
}
},
"responses" : {
"201" : {
"description" : " Organization created successfully" ,
"content" : {
"application/json" : {
"schema" : {"$ref" : " #/components/schemas/Organization" }
}
}
},
"401" : {"$ref" : " #/components/responses/Unauthorized" },
"403" : {"$ref" : " #/components/responses/Forbidden" },
"422" : {"$ref" : " #/components/responses/ValidationError" },
"429" : {"$ref" : " #/components/responses/RateLimitExceeded" }
}
}
},
"/organizations/{id}" : {
"get" : {
"summary" : " Get organization details" ,
"description" : " Retrieve detailed information about a specific organization, including white-label configuration, license status, and resource usage." ,
"operationId" : " getOrganization" ,
"tags" : [" Organizations" ],
"security" : [{"sanctum" : [" organization:read" ]}],
"parameters" : [
{
"name" : " id" ,
"in" : " path" ,
"required" : true ,
"description" : " Organization ID or slug" ,
"schema" : {"type" : " string" , "example" : " 42" }
}
],
"responses" : {
"200" : {
"description" : " Successful response" ,
"content" : {
"application/json" : {
"schema" : {
"allOf" : [
{"$ref" : " #/components/schemas/Organization" },
{
"type" : " object" ,
"properties" : {
"white_label_config" : {"$ref" : " #/components/schemas/WhiteLabelConfig" },
"license" : {"type" : " object" },
"resource_usage" : {"type" : " object" }
}
}
]
}
}
}
},
"401" : {"$ref" : " #/components/responses/Unauthorized" },
"403" : {"$ref" : " #/components/responses/Forbidden" },
"404" : {"$ref" : " #/components/responses/NotFound" },
"429" : {"$ref" : " #/components/responses/RateLimitExceeded" }
}
}
},
"/terraform/deployments" : {
"post" : {
"summary" : " Provision cloud infrastructure" ,
"description" : " Initiate a Terraform deployment to provision cloud servers. This is an asynchronous operation - use the returned deployment ID to poll for status." ,
"operationId" : " provisionInfrastructure" ,
"tags" : [" Infrastructure" ],
"security" : [{"sanctum" : [" infrastructure:write" ]}],
"requestBody" : {
"required" : true ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"organization_id" : {"type" : " integer" , "example" : 42 },
"provider" : {"type" : " string" , "enum" : [" aws" , " digitalocean" , " hetzner" ], "example" : " aws" },
"region" : {"type" : " string" , "example" : " us-east-1" },
"instance_type" : {"type" : " string" , "example" : " t3.medium" },
"instance_count" : {"type" : " integer" , "minimum" : 1 , "maximum" : 50 , "example" : 3 },
"cloud_credential_id" : {"type" : " integer" , "description" : " ID of stored cloud provider credentials" , "example" : 7 }
},
"required" : [" organization_id" , " provider" , " region" , " instance_type" , " instance_count" , " cloud_credential_id" ]
}
}
}
},
"responses" : {
"202" : {
"description" : " Deployment initiated successfully" ,
"content" : {
"application/json" : {
"schema" : {
"type" : " object" ,
"properties" : {
"message" : {"type" : " string" , "example" : " Infrastructure provisioning initiated" },
"deployment" : {"$ref" : " #/components/schemas/TerraformDeployment" }
}
}
}
}
},
"401" : {"$ref" : " #/components/responses/Unauthorized" },
"403" : {"$ref" : " #/components/responses/Forbidden" },
"422" : {"$ref" : " #/components/responses/ValidationError" },
"429" : {"$ref" : " #/components/responses/RateLimitExceeded" }
}
}
}
}
}
Authentication Documentation
File: docs/api/authentication.md
# API Authentication
Coolify Enterprise uses ** Laravel Sanctum** for API authentication with organization-scoped tokens.
## Generating API Tokens
### Step 1: Login to obtain session
``` bash
curl -X POST https://api.coolify.io/v1/auth/login \
-H " Content-Type: application/json" \
-d ' {
"email": "admin@acme.com",
"password": "your-secure-password"
}'
Response:
{
"user" : {
"id" : 123 ,
"name" : " Admin User" ,
"email" : " admin@acme.com"
},
"organizations" : [
{"id" : 42 , "name" : " Acme Corporation" , "role" : " admin" }
]
}
Step 2: Generate organization-scoped token
curl -X POST https://api.coolify.io/v1/auth/tokens \
-H " Content-Type: application/json" \
-H " Authorization: Bearer {session-token}" \
-d ' {
"name": "Production API Key",
"organization_id": 42,
"abilities": [
"organization:read",
"organization:write",
"infrastructure:read",
"infrastructure:write",
"application:deploy"
],
"expires_at": "2025-12-31"
}'
Response:
{
"token" : " 1|aB3dEf5gHiJkLmNoPqRsTuVwXyZ" ,
"abilities" : [" organization:read" , " organization:write" , ... ],
"expires_at" : " 2025-12-31T23:59:59Z"
}
Step 3: Use token in API requests
curl -X GET https://api.coolify.io/v1/organizations \
-H " Authorization: Bearer 1|aB3dEf5gHiJkLmNoPqRsTuVwXyZ" \
-H " Accept: application/json"
Token Abilities (Scopes)
Ability
Description
organization:read
View organization details, users, settings
organization:write
Create/update organizations, manage users
infrastructure:read
View servers, deployments, resource metrics
infrastructure:write
Provision servers, modify infrastructure
application:read
View applications and their configurations
application:write
Create/update applications
application:deploy
Trigger application deployments
payment:read
View subscriptions and billing information
payment:write
Update payment methods, change subscriptions
domain:read
View domain configurations
domain:write
Register domains, modify DNS records
Security Best Practices
Token Rotation : Rotate API tokens every 90 days
Principle of Least Privilege : Grant only necessary abilities
IP Allowlisting : Restrict tokens to known IP ranges (enterprise tier)
Token Expiration : Always set expiration dates
Secure Storage : Store tokens in environment variables or secrets managers (never commit to git)
Example: Multi-Language Integration
PHP (Laravel/Guzzle)
use GuzzleHttp \Client ;
$ client = new Client ([
'base_uri ' => 'https://api.coolify.io/v1/ ' ,
'headers ' => [
'Authorization ' => 'Bearer ' . env ('COOLIFY_API_TOKEN ' ),
'Accept ' => 'application/json ' ,
],
]);
$ response = $ client ->get ('organizations ' );
$ organizations = json_decode ($ response ->getBody (), true );
JavaScript (Node.js/Axios)
const axios = require ( 'axios' ) ;
const client = axios . create ( {
baseURL : 'https://api.coolify.io/v1' ,
headers : {
'Authorization' : `Bearer ${ process . env . COOLIFY_API_TOKEN } ` ,
'Accept' : 'application/json' ,
} ,
} ) ;
const organizations = await client . get ( '/organizations' ) ;
console . log ( organizations . data ) ;
Python (Requests)
import requests
import os
headers = {
'Authorization' : f'Bearer { os .getenv ("COOLIFY_API_TOKEN" )} ' ,
'Accept' : 'application/json' ,
}
response = requests .get ('https://api.coolify.io/v1/organizations' , headers = headers )
organizations = response .json ()
### Rate Limiting Documentation
**File:** `docs/api/rate-limiting.md`
```markdown
# API Rate Limiting
Coolify Enterprise enforces tiered rate limiting based on your organization's license.
## Rate Limit Tiers
| Tier | Requests/Minute | Requests/Hour | Burst Allowance |
|------|-----------------|---------------|-----------------|
| **Starter** | 100 | 5,000 | +20 |
| **Professional** | 500 | 25,000 | +100 |
| **Enterprise** | 2,000 | 100,000 | +500 |
**Burst Allowance**: Temporary extra requests allowed above the per-minute limit.
## Rate Limit Headers
Every API response includes rate limit information:
```http
HTTP/1.1 200 OK
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 1678901234
Header
Description
X-RateLimit-Limit
Maximum requests allowed in current window
X-RateLimit-Remaining
Requests remaining before rate limit
X-RateLimit-Reset
Unix timestamp when rate limit resets
Handling Rate Limit Exceeded (429)
When rate limit is exceeded, you'll receive:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Reset: 1678901234
Content-Type: application/json
{
"message" : " Too Many Requests"
}
Recommended Retry Strategy
async function makeRequestWithRetry ( url , options , maxRetries = 3 ) {
for ( let i = 0 ; i < maxRetries ; i ++ ) {
try {
const response = await fetch ( url , options ) ;
if ( response . status === 429 ) {
const retryAfter = parseInt ( response . headers . get ( 'Retry-After' ) || '60' ) ;
console . log ( `Rate limit exceeded. Waiting ${ retryAfter } seconds...` ) ;
await sleep ( retryAfter * 1000 ) ;
continue ;
}
return response ;
} catch ( error ) {
if ( i === maxRetries - 1 ) throw error ;
await sleep ( Math . pow ( 2 , i ) * 1000 ) ; // Exponential backoff
}
}
}
Optimizing API Usage
Caching : Cache responses locally when data doesn't change frequently
Batch Operations : Use bulk endpoints when available (e.g., /applications/bulk-deploy)
Webhooks : Subscribe to webhooks instead of polling
Pagination : Request only the data you need with per_page parameter
Conditional Requests : Use If-None-Match with ETags to avoid unnecessary transfers
Enterprise Custom Limits
Enterprise tier organizations can request custom rate limits. Contact support with your use case.
### Code Examples
**File:** `docs/api/examples/php/provision-infrastructure.php`
```php
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
'base_uri' => 'https://api.coolify.io/v1/',
'headers' => [
'Authorization' => 'Bearer ' . getenv('COOLIFY_API_TOKEN'),
'Accept' => 'application/json',
],
]);
/**
* Provision AWS infrastructure with 3 t3.medium instances
*/
function provisionInfrastructure(Client $client, int $organizationId): array
{
try {
$response = $client->post('terraform/deployments', [
'json' => [
'organization_id' => $organizationId,
'provider' => 'aws',
'region' => 'us-east-1',
'instance_type' => 't3.medium',
'instance_count' => 3,
'cloud_credential_id' => 7,
],
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
if ($e->hasResponse()) {
$statusCode = $e->getResponse()->getStatusCode();
$body = json_decode($e->getResponse()->getBody(), true);
if ($statusCode === 429) {
$retryAfter = $e->getResponse()->getHeader('Retry-After')[0] ?? 60;
echo "Rate limit exceeded. Retry after {$retryAfter} seconds.\n";
sleep($retryAfter);
return provisionInfrastructure($client, $organizationId); // Retry
}
if ($statusCode === 422) {
echo "Validation error:\n";
print_r($body['errors']);
}
}
throw $e;
}
}
/**
* Poll deployment status until completion
*/
function pollDeploymentStatus(Client $client, int $deploymentId, int $maxAttempts = 60): array
{
for ($i = 0; $i < $maxAttempts; $i++) {
$response = $client->get("terraform/deployments/{$deploymentId}");
$deployment = json_decode($response->getBody(), true);
echo "Status: {$deployment['status']}\n";
if ($deployment['status'] === 'completed') {
return $deployment;
}
if ($deployment['status'] === 'failed') {
throw new Exception("Deployment failed: " . ($deployment['error_message'] ?? 'Unknown error'));
}
sleep(10); // Wait 10 seconds before next poll
}
throw new Exception("Deployment timed out after {$maxAttempts} attempts");
}
// Execute provisioning
$deployment = provisionInfrastructure($client, 42);
echo "Deployment initiated: {$deployment['deployment']['id']}\n";
// Wait for completion
$completedDeployment = pollDeploymentStatus($client, $deployment['deployment']['id']);
echo "Provisioning complete!\n";
echo "Servers created:\n";
print_r($completedDeployment['terraform_output']['servers']);
File: docs/api/examples/javascript/provision-infrastructure.js
const axios = require ( 'axios' ) ;
const client = axios . create ( {
baseURL : 'https://api.coolify.io/v1' ,
headers : {
'Authorization' : `Bearer ${ process . env . COOLIFY_API_TOKEN } ` ,
'Accept' : 'application/json' ,
} ,
} ) ;
/**
* Provision AWS infrastructure
*/
async function provisionInfrastructure ( organizationId ) {
try {
const response = await client . post ( '/terraform/deployments' , {
organization_id : organizationId ,
provider : 'aws' ,
region : 'us-east-1' ,
instance_type : 't3.medium' ,
instance_count : 3 ,
cloud_credential_id : 7 ,
} ) ;
return response . data ;
} catch ( error ) {
if ( error . response ?. status === 429 ) {
const retryAfter = parseInt ( error . response . headers [ 'retry-after' ] || '60' ) ;
console . log ( `Rate limit exceeded. Waiting ${ retryAfter } seconds...` ) ;
await sleep ( retryAfter * 1000 ) ;
return provisionInfrastructure ( organizationId ) ; // Retry
}
if ( error . response ?. status === 422 ) {
console . error ( 'Validation errors:' , error . response . data . errors ) ;
}
throw error ;
}
}
/**
* Poll deployment status
*/
async function pollDeploymentStatus ( deploymentId , maxAttempts = 60 ) {
for ( let i = 0 ; i < maxAttempts ; i ++ ) {
const response = await client . get ( `/terraform/deployments/${ deploymentId } ` ) ;
const deployment = response . data ;
console . log ( `Status: ${ deployment . status } ` ) ;
if ( deployment . status === 'completed' ) {
return deployment ;
}
if ( deployment . status === 'failed' ) {
throw new Error ( `Deployment failed: ${ deployment . error_message || 'Unknown error' } ` ) ;
}
await sleep ( 10000 ) ; // Wait 10 seconds
}
throw new Error ( `Deployment timed out after ${ maxAttempts } attempts` ) ;
}
function sleep ( ms ) {
return new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
}
// Execute
( async ( ) => {
try {
const deployment = await provisionInfrastructure ( 42 ) ;
console . log ( `Deployment initiated: ${ deployment . deployment . id } ` ) ;
const completed = await pollDeploymentStatus ( deployment . deployment . id ) ;
console . log ( 'Provisioning complete!' ) ;
console . log ( 'Servers:' , completed . terraform_output . servers ) ;
} catch ( error ) {
console . error ( 'Error:' , error . message ) ;
process . exit ( 1 ) ;
}
} ) ( ) ;
File: docs/api/examples/python/provision-infrastructure.py
import requests
import time
import os
from typing import Dict , Optional
API_BASE = 'https://api.coolify.io/v1'
API_TOKEN = os .getenv ('COOLIFY_API_TOKEN' )
headers = {
'Authorization' : f'Bearer { API_TOKEN } ' ,
'Accept' : 'application/json' ,
}
def provision_infrastructure (organization_id : int ) -> Dict :
"""Provision AWS infrastructure"""
payload = {
'organization_id' : organization_id ,
'provider' : 'aws' ,
'region' : 'us-east-1' ,
'instance_type' : 't3.medium' ,
'instance_count' : 3 ,
'cloud_credential_id' : 7 ,
}
try :
response = requests .post (
f'{ API_BASE } /terraform/deployments' ,
json = payload ,
headers = headers
)
response .raise_for_status ()
return response .json ()
except requests .exceptions .HTTPError as e :
if e .response .status_code == 429 :
retry_after = int (e .response .headers .get ('Retry-After' , 60 ))
print (f'Rate limit exceeded. Waiting { retry_after } seconds...' )
time .sleep (retry_after )
return provision_infrastructure (organization_id ) # Retry
if e .response .status_code == 422 :
print ('Validation errors:' , e .response .json ().get ('errors' ))
raise
def poll_deployment_status (deployment_id : int , max_attempts : int = 60 ) -> Dict :
"""Poll deployment status until completion"""
for i in range (max_attempts ):
response = requests .get (
f'{ API_BASE } /terraform/deployments/{ deployment_id } ' ,
headers = headers
)
response .raise_for_status ()
deployment = response .json ()
print (f'Status: { deployment ["status" ]} ' )
if deployment ['status' ] == 'completed' :
return deployment
if deployment ['status' ] == 'failed' :
error_msg = deployment .get ('error_message' , 'Unknown error' )
raise Exception (f'Deployment failed: { error_msg } ' )
time .sleep (10 ) # Wait 10 seconds
raise Exception (f'Deployment timed out after { max_attempts } attempts' )
if __name__ == '__main__' :
try :
# Provision infrastructure
deployment = provision_infrastructure (42 )
print (f'Deployment initiated: { deployment ["deployment" ]["id" ]} ' )
# Wait for completion
completed = poll_deployment_status (deployment ['deployment' ]['id' ])
print ('Provisioning complete!' )
print ('Servers:' , completed ['terraform_output' ]['servers' ])
except Exception as e :
print (f'Error: { str (e )} ' )
exit (1 )
Swagger UI Integration
File: resources/views/api/documentation.blade.php
<!DOCTYPE html>
<html lang =" en" >
<head >
<meta charset =" UTF-8" >
<meta name =" viewport" content =" width=device-width, initial-scale=1.0" >
<title >Coolify Enterprise API Documentation</title >
<link rel =" stylesheet" href =" https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" >
<style >
body {
margin : 0 ;
padding : 0 ;
}
.topbar {
display : none ;
}
</style >
</head >
<body >
<div id =" swagger-ui" ></div >
<script src =" https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" ></script >
<script src =" https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-standalone-preset.js" ></script >
<script >
window .onload = function () {
const ui = SwaggerUIBundle ({
url: " {{ url (' /api/openapi.json' ) } }" ,
dom_id: ' #swagger-ui' ,
deepLinking: true ,
presets: [
SwaggerUIBundle .presets .apis ,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle .plugins .DownloadUrl
],
layout: " StandaloneLayout" ,
persistAuthorization: true ,
tryItOutEnabled: true ,
filter: true ,
supportedSubmitMethods: [' get' , ' post' , ' put' , ' patch' , ' delete' ],
});
window .ui = ui;
}
</script >
</body >
</html >
Route: Add to routes/web.php
Route::get ('/api/documentation ' , function () {
return view ('api.documentation ' );
})->name ('api.documentation ' );
Route::get ('/api/openapi.json ' , function () {
return response ()->file (storage_path ('api-docs/openapi.json ' ));
})->name ('api.openapi ' );
Implementation Approach
Step 1: Enhance OpenAPI Specification (2-3 hours)
Review auto-generated OpenAPI spec from L5-Swagger
Add detailed descriptions for all endpoints
Add request/response examples
Define all schemas for enterprise models
Add security schemes and scopes
Document all error responses with examples
Step 2: Write Core Documentation Files (4-5 hours)
Create docs/api/README.md landing page
Write authentication.md with step-by-step token generation
Write rate-limiting.md with tier comparison and retry strategies
Write endpoint-specific guides (organizations.md, white-label.md, etc.)
Write webhooks.md with HMAC validation examples
Write errors.md reference with all status codes
Step 3: Create Code Examples (3-4 hours)
Write PHP examples using Guzzle (5+ examples)
Write JavaScript/Node.js examples using Axios (5+ examples)
Write Python examples using Requests library (5+ examples)
Write cURL examples for all major endpoints (10+ examples)
Test all code examples against staging API
Step 4: Swagger UI Integration (1-2 hours)
Create Blade view for Swagger UI
Add routes for /api/documentation and /api/openapi.json
Configure Swagger UI with authentication persistence
Test "Try it out" functionality for all endpoints
Add custom branding to Swagger UI (optional)
Step 5: Additional Resources (2-3 hours)
Export Postman collection from OpenAPI spec
Test Postman collection with all endpoints
Write migration guide from standard Coolify
Create pagination guide with cursor/offset examples
Write security best practices section
Step 6: Documentation Site Setup (Optional, 2-3 hours)
Set up static documentation generator (VitePress, Docsify, or similar)
Implement search functionality
Add dark mode support
Create responsive navigation
Deploy documentation site
Step 7: Review and Testing (1-2 hours)
Technical review by backend team
Test all code examples
Verify all links work
Check for typos and formatting issues
Validate OpenAPI spec with online validators
Step 8: Publish and Maintain (1 hour)
Publish documentation to production
Add documentation links to main application
Set up changelog for API updates
Create process for keeping docs in sync with code changes
Test Strategy
Documentation Quality Tests
Manual Testing Checklist:
Automated Tests
File: tests/Feature/Documentation/ApiDocumentationTest.php
<?php
use Illuminate \Support \Facades \Storage ;
it ('serves OpenAPI specification ' , function () {
$ response = $ this ->get ('/api/openapi.json ' );
$ response ->assertOk ()
->assertHeader ('Content-Type ' , 'application/json ' );
$ spec = json_decode ($ response ->getContent (), true );
expect ($ spec )->toHaveKeys (['openapi ' , 'info ' , 'paths ' , 'components ' ]);
expect ($ spec ['openapi ' ])->toBe ('3.1.0 ' );
});
it ('loads Swagger UI documentation page ' , function () {
$ response = $ this ->get ('/api/documentation ' );
$ response ->assertOk ()
->assertSee ('swagger-ui ' )
->assertSee ('Coolify Enterprise API ' );
});
it ('includes all enterprise endpoints in OpenAPI spec ' , function () {
$ response = $ this ->get ('/api/openapi.json ' );
$ spec = json_decode ($ response ->getContent (), true );
$ requiredEndpoints = [
'/organizations ' ,
'/organizations/{id} ' ,
'/terraform/deployments ' ,
'/white-label/config ' ,
'/monitoring/metrics ' ,
'/payments/subscriptions ' ,
'/domains ' ,
];
foreach ($ requiredEndpoints as $ endpoint ) {
expect ($ spec ['paths ' ])->toHaveKey ($ endpoint );
}
});
it ('includes rate limit response schemas ' , function () {
$ response = $ this ->get ('/api/openapi.json ' );
$ spec = json_decode ($ response ->getContent (), true );
expect ($ spec ['components ' ]['responses ' ])->toHaveKey ('RateLimitExceeded ' );
expect ($ spec ['components ' ]['schemas ' ])->toHaveKey ('RateLimitHeaders ' );
});
it ('validates OpenAPI spec structure ' , function () {
$ specPath = storage_path ('api-docs/openapi.json ' );
expect (file_exists ($ specPath ))->toBeTrue ();
$ spec = json_decode (file_get_contents ($ specPath ), true );
// Validate required top-level fields
expect ($ spec )->toHaveKeys (['openapi ' , 'info ' , 'servers ' , 'paths ' , 'components ' ]);
// Validate info section
expect ($ spec ['info ' ])->toHaveKeys (['title ' , 'version ' , 'description ' ]);
// Validate security schemes
expect ($ spec ['components ' ]['securitySchemes ' ])->toHaveKey ('sanctum ' );
});
Integration Tests
File: tests/Feature/Documentation/CodeExamplesTest.php
<?php
it ('PHP example code is syntactically valid ' , function () {
$ exampleFiles = glob (base_path ('docs/api/examples/php/*.php ' ));
foreach ($ exampleFiles as $ file ) {
$ output = shell_exec ("php -l {$ file } 2>&1 " );
expect ($ output )->toContain ('No syntax errors detected ' );
}
});
it ('JavaScript example code is syntactically valid ' , function () {
$ exampleFiles = glob (base_path ('docs/api/examples/javascript/*.js ' ));
foreach ($ exampleFiles as $ file ) {
$ output = shell_exec ("node --check {$ file } 2>&1 " );
expect ($ output )->toBeEmpty (); // No output means valid
}
});
it ('Python example code is syntactically valid ' , function () {
$ exampleFiles = glob (base_path ('docs/api/examples/python/*.py ' ));
foreach ($ exampleFiles as $ file ) {
$ output = shell_exec ("python3 -m py_compile {$ file } 2>&1 " );
expect ($ output )->toBeEmpty (); // No output means valid
}
});
Definition of Done
Related Tasks
Depends on: Task 61 (Enhanced API System) - all documented endpoints must exist first
Depends on: Task 54 (Rate Limiting) - rate limit tiers must be implemented to document
Depends on: Task 52 (Sanctum Extensions) - organization-scoped auth must work to document
Depends on: Task 58 (Swagger UI Integration) - Swagger UI integration provides interactive docs
Depends on: Task 57 (OpenAPI Spec) - OpenAPI spec is the foundation for all documentation
Referenced by: All enterprise tasks - comprehensive docs help developers integrate with all features
Task: Write API documentation with interactive examples for Enterprise Coolify
Description
Create comprehensive, production-ready API documentation for the Coolify Enterprise Transformation project. This documentation covers all new enterprise endpoints (organizations, white-label branding, Terraform infrastructure, resource monitoring, payment processing, domain management) with interactive examples, authentication guides, and complete code samples for multiple programming languages.
Why This Task is Critical:
API documentation is the primary interface between the platform and third-party developers, integration partners, and automation scripts. Without comprehensive, accurate documentation, enterprise customers cannot effectively:
Professional API documentation transforms the platform from "possible to integrate" to "easy to integrate," directly impacting customer satisfaction, time-to-value, and platform adoption rates. Interactive examples allow developers to test API calls directly from the browser, reducing integration time from days to hours.
What Makes This Documentation Unique:
Unlike standard Coolify API docs, this enterprise documentation includes:
Integration Architecture:
The API documentation integrates with several existing and new systems:
Scope of Documentation:
Core Enterprise APIs (15+ endpoints):
Authentication & Authorization (3 chapters):
Advanced Topics (5 chapters):
Interactive Examples (Swagger UI):
Output Deliverables:
/docs/api/openapi.json(auto-generated, enhanced with examples)/docs/api/*.md(human-readable guides and tutorials)/api/documentationroute (interactive API explorer)/docs/api/examples/{language}/*.{ext}(PHP, JavaScript, Python, cURL)/docs/api/Coolify-Enterprise.postman_collection.json/docs/api/migration-from-standard-coolify.mdAcceptance Criteria
/api/documentationroute with working "Try it out" functionalityTechnical Details
File Paths
Documentation Files:
/home/topgun/topgun/docs/api/README.md(new - main API documentation landing page)/home/topgun/topgun/docs/api/authentication.md(new - Sanctum token guide)/home/topgun/topgun/docs/api/rate-limiting.md(new - rate limit guide)/home/topgun/topgun/docs/api/organizations.md(new - organization API reference)/home/topgun/topgun/docs/api/white-label.md(new - branding API reference)/home/topgun/topgun/docs/api/infrastructure.md(new - Terraform API reference)/home/topgun/topgun/docs/api/monitoring.md(new - resource monitoring API reference)/home/topgun/topgun/docs/api/payments.md(new - payment API reference)/home/topgun/topgun/docs/api/domains.md(new - domain management API reference)/home/topgun/topgun/docs/api/webhooks.md(new - webhook integration guide)/home/topgun/topgun/docs/api/errors.md(new - error reference)/home/topgun/topgun/docs/api/pagination.md(new - pagination strategies)/home/topgun/topgun/docs/api/migration.md(new - migration guide)/home/topgun/topgun/docs/api/changelog.md(new - API changelog)Code Example Files:
/home/topgun/topgun/docs/api/examples/php/*.php(new - Laravel/Guzzle examples)/home/topgun/topgun/docs/api/examples/javascript/*.js(new - Node.js/Axios examples)/home/topgun/topgun/docs/api/examples/python/*.py(new - Requests library examples)/home/topgun/topgun/docs/api/examples/curl/*.sh(new - cURL examples)OpenAPI Specification:
/home/topgun/topgun/storage/api-docs/openapi.json(enhanced - auto-generated with custom annotations)Swagger UI Integration:
/home/topgun/topgun/resources/views/api/documentation.blade.php(new - Swagger UI view)/home/topgun/topgun/routes/web.php(modify - add/api/documentationroute)Postman Collection:
/home/topgun/topgun/docs/api/Coolify-Enterprise.postman_collection.json(new - exported collection)OpenAPI Specification Enhancement
File:
storage/api-docs/openapi.json(enhanced with custom annotations)The existing OpenAPI spec (generated by L5-Swagger or similar) needs enhancement with:
{ "openapi": "3.1.0", "info": { "title": "Coolify Enterprise API", "description": "Comprehensive API for multi-tenant infrastructure provisioning, application deployment, and white-label branding. Supports organization hierarchies, tiered rate limiting, and real-time resource monitoring.", "version": "1.0.0", "contact": { "name": "Coolify Enterprise Support", "email": "enterprise@coolify.io", "url": "https://enterprise.coolify.io/support" }, "license": { "name": "Proprietary", "url": "https://enterprise.coolify.io/license" } }, "servers": [ { "url": "https://api.coolify.io/v1", "description": "Production API" }, { "url": "https://staging-api.coolify.io/v1", "description": "Staging API" }, { "url": "http://localhost:8000/api/v1", "description": "Local Development" } ], "security": [ { "sanctum": ["organization:read", "organization:write"] } ], "components": { "securitySchemes": { "sanctum": { "type": "http", "scheme": "bearer", "bearerFormat": "Sanctum Token", "description": "Use a Sanctum personal access token with organization-scoped abilities. Generate tokens via POST /api/v1/auth/tokens with organization_id and abilities array." } }, "schemas": { "Organization": { "type": "object", "properties": { "id": {"type": "integer", "example": 42}, "name": {"type": "string", "example": "Acme Corporation"}, "slug": {"type": "string", "example": "acme-corp"}, "type": { "type": "string", "enum": ["top_branch", "master_branch", "sub_user", "end_user"], "example": "master_branch" }, "parent_id": {"type": "integer", "nullable": true, "example": 1}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"} }, "required": ["id", "name", "slug", "type"] }, "WhiteLabelConfig": { "type": "object", "properties": { "id": {"type": "integer"}, "organization_id": {"type": "integer"}, "platform_name": {"type": "string", "example": "Acme Cloud Platform"}, "primary_color": {"type": "string", "pattern": "^#[0-9A-F]{6}$", "example": "#3B82F6"}, "secondary_color": {"type": "string", "pattern": "^#[0-9A-F]{6}$", "example": "#8B5CF6"}, "accent_color": {"type": "string", "pattern": "^#[0-9A-F]{6}$", "example": "#10B981"}, "logo_url": {"type": "string", "format": "uri", "example": "https://storage.coolify.io/branding/42/logo.png"}, "favicon_url": {"type": "string", "format": "uri", "nullable": true}, "custom_css": {"type": "string", "nullable": true} } }, "TerraformDeployment": { "type": "object", "properties": { "id": {"type": "integer"}, "organization_id": {"type": "integer"}, "provider": {"type": "string", "enum": ["aws", "digitalocean", "hetzner", "gcp", "azure"]}, "status": {"type": "string", "enum": ["pending", "planning", "applying", "completed", "failed", "destroying"]}, "instance_count": {"type": "integer", "example": 3}, "instance_type": {"type": "string", "example": "t3.medium"}, "region": {"type": "string", "example": "us-east-1"}, "terraform_output": {"type": "object", "description": "Parsed Terraform output with server IPs and IDs"} } }, "Error": { "type": "object", "properties": { "message": {"type": "string", "example": "The given data was invalid."}, "errors": { "type": "object", "additionalProperties": { "type": "array", "items": {"type": "string"} }, "example": { "name": ["The name field is required."], "email": ["The email must be a valid email address."] } } } }, "RateLimitHeaders": { "type": "object", "properties": { "X-RateLimit-Limit": {"type": "integer", "description": "Maximum requests allowed per window", "example": 500}, "X-RateLimit-Remaining": {"type": "integer", "description": "Requests remaining in current window", "example": 487}, "X-RateLimit-Reset": {"type": "integer", "description": "Unix timestamp when rate limit resets", "example": 1678901234}, "Retry-After": {"type": "integer", "description": "Seconds to wait before retrying (only on 429)", "example": 42} } } }, "responses": { "Unauthorized": { "description": "Authentication token is missing or invalid", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": {"type": "string", "example": "Unauthenticated."} } } } } }, "Forbidden": { "description": "Authenticated but lacking required permissions", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": {"type": "string", "example": "This action is unauthorized."} } } } } }, "NotFound": { "description": "Resource not found or not accessible in your organization", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": {"type": "string", "example": "Resource not found."} } } } } }, "ValidationError": { "description": "Request validation failed", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Error"} } } }, "RateLimitExceeded": { "description": "Rate limit exceeded for your tier", "headers": { "X-RateLimit-Limit": {"schema": {"type": "integer"}}, "X-RateLimit-Remaining": {"schema": {"type": "integer"}}, "X-RateLimit-Reset": {"schema": {"type": "integer"}}, "Retry-After": {"schema": {"type": "integer"}} }, "content": { "application/json": { "schema": { "type": "object", "properties": { "message": {"type": "string", "example": "Too Many Requests"} } } } } } } }, "paths": { "/organizations": { "get": { "summary": "List all organizations accessible to the authenticated user", "description": "Returns a paginated list of organizations where the user has any role. Includes organization hierarchy information (parent/child relationships). Results are automatically scoped to the user's access.", "operationId": "listOrganizations", "tags": ["Organizations"], "security": [{"sanctum": ["organization:read"]}], "parameters": [ { "name": "page", "in": "query", "description": "Page number for pagination (1-indexed)", "schema": {"type": "integer", "default": 1, "minimum": 1} }, { "name": "per_page", "in": "query", "description": "Number of results per page", "schema": {"type": "integer", "default": 15, "minimum": 1, "maximum": 100} }, { "name": "type", "in": "query", "description": "Filter by organization type", "schema": { "type": "string", "enum": ["top_branch", "master_branch", "sub_user", "end_user"] } } ], "responses": { "200": { "description": "Successful response with paginated organizations", "headers": { "X-RateLimit-Limit": {"schema": {"type": "integer"}}, "X-RateLimit-Remaining": {"schema": {"type": "integer"}}, "X-RateLimit-Reset": {"schema": {"type": "integer"}} }, "content": { "application/json": { "schema": { "type": "object", "properties": { "data": { "type": "array", "items": {"$ref": "#/components/schemas/Organization"} }, "meta": { "type": "object", "properties": { "current_page": {"type": "integer", "example": 1}, "per_page": {"type": "integer", "example": 15}, "total": {"type": "integer", "example": 47}, "last_page": {"type": "integer", "example": 4} } }, "links": { "type": "object", "properties": { "first": {"type": "string", "format": "uri"}, "last": {"type": "string", "format": "uri"}, "prev": {"type": "string", "format": "uri", "nullable": true}, "next": {"type": "string", "format": "uri", "nullable": true} } } } }, "examples": { "success": { "summary": "Successful response", "value": { "data": [ { "id": 42, "name": "Acme Corporation", "slug": "acme-corp", "type": "master_branch", "parent_id": 1, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-03-20T14:22:00Z" } ], "meta": { "current_page": 1, "per_page": 15, "total": 47, "last_page": 4 }, "links": { "first": "https://api.coolify.io/v1/organizations?page=1", "last": "https://api.coolify.io/v1/organizations?page=4", "prev": null, "next": "https://api.coolify.io/v1/organizations?page=2" } } } } } } }, "401": {"$ref": "#/components/responses/Unauthorized"}, "429": {"$ref": "#/components/responses/RateLimitExceeded"} } }, "post": { "summary": "Create a new organization", "description": "Creates a new organization under the authenticated user's current organization (if hierarchical structure). Requires 'organization:write' ability.", "operationId": "createOrganization", "tags": ["Organizations"], "security": [{"sanctum": ["organization:write"]}], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": {"type": "string", "minLength": 1, "maxLength": 255, "example": "New Organization"}, "slug": {"type": "string", "pattern": "^[a-z0-9-]+$", "example": "new-org"}, "type": { "type": "string", "enum": ["top_branch", "master_branch", "sub_user", "end_user"], "example": "master_branch" }, "parent_id": {"type": "integer", "nullable": true, "example": 1} }, "required": ["name", "type"] }, "examples": { "master_branch": { "summary": "Create master branch organization", "value": { "name": "Acme Corporation", "slug": "acme-corp", "type": "master_branch", "parent_id": 1 } } } } } }, "responses": { "201": { "description": "Organization created successfully", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/Organization"} } } }, "401": {"$ref": "#/components/responses/Unauthorized"}, "403": {"$ref": "#/components/responses/Forbidden"}, "422": {"$ref": "#/components/responses/ValidationError"}, "429": {"$ref": "#/components/responses/RateLimitExceeded"} } } }, "/organizations/{id}": { "get": { "summary": "Get organization details", "description": "Retrieve detailed information about a specific organization, including white-label configuration, license status, and resource usage.", "operationId": "getOrganization", "tags": ["Organizations"], "security": [{"sanctum": ["organization:read"]}], "parameters": [ { "name": "id", "in": "path", "required": true, "description": "Organization ID or slug", "schema": {"type": "string", "example": "42"} } ], "responses": { "200": { "description": "Successful response", "content": { "application/json": { "schema": { "allOf": [ {"$ref": "#/components/schemas/Organization"}, { "type": "object", "properties": { "white_label_config": {"$ref": "#/components/schemas/WhiteLabelConfig"}, "license": {"type": "object"}, "resource_usage": {"type": "object"} } } ] } } } }, "401": {"$ref": "#/components/responses/Unauthorized"}, "403": {"$ref": "#/components/responses/Forbidden"}, "404": {"$ref": "#/components/responses/NotFound"}, "429": {"$ref": "#/components/responses/RateLimitExceeded"} } } }, "/terraform/deployments": { "post": { "summary": "Provision cloud infrastructure", "description": "Initiate a Terraform deployment to provision cloud servers. This is an asynchronous operation - use the returned deployment ID to poll for status.", "operationId": "provisionInfrastructure", "tags": ["Infrastructure"], "security": [{"sanctum": ["infrastructure:write"]}], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "organization_id": {"type": "integer", "example": 42}, "provider": {"type": "string", "enum": ["aws", "digitalocean", "hetzner"], "example": "aws"}, "region": {"type": "string", "example": "us-east-1"}, "instance_type": {"type": "string", "example": "t3.medium"}, "instance_count": {"type": "integer", "minimum": 1, "maximum": 50, "example": 3}, "cloud_credential_id": {"type": "integer", "description": "ID of stored cloud provider credentials", "example": 7} }, "required": ["organization_id", "provider", "region", "instance_type", "instance_count", "cloud_credential_id"] } } } }, "responses": { "202": { "description": "Deployment initiated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": {"type": "string", "example": "Infrastructure provisioning initiated"}, "deployment": {"$ref": "#/components/schemas/TerraformDeployment"} } } } } }, "401": {"$ref": "#/components/responses/Unauthorized"}, "403": {"$ref": "#/components/responses/Forbidden"}, "422": {"$ref": "#/components/responses/ValidationError"}, "429": {"$ref": "#/components/responses/RateLimitExceeded"} } } } } }Authentication Documentation
File:
docs/api/authentication.mdResponse:
{ "user": { "id": 123, "name": "Admin User", "email": "admin@acme.com" }, "organizations": [ {"id": 42, "name": "Acme Corporation", "role": "admin"} ] }Step 2: Generate organization-scoped token
Response:
{ "token": "1|aB3dEf5gHiJkLmNoPqRsTuVwXyZ", "abilities": ["organization:read", "organization:write", ...], "expires_at": "2025-12-31T23:59:59Z" }Step 3: Use token in API requests
Token Abilities (Scopes)
organization:readorganization:writeinfrastructure:readinfrastructure:writeapplication:readapplication:writeapplication:deploypayment:readpayment:writedomain:readdomain:writeSecurity Best Practices
Example: Multi-Language Integration
PHP (Laravel/Guzzle)
JavaScript (Node.js/Axios)
Python (Requests)
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-ResetHandling Rate Limit Exceeded (429)
When rate limit is exceeded, you'll receive:
Recommended Retry Strategy
Optimizing API Usage
/applications/bulk-deploy)per_pageparameterIf-None-Matchwith ETags to avoid unnecessary transfersEnterprise Custom Limits
Enterprise tier organizations can request custom rate limits. Contact support with your use case.
File:
docs/api/examples/javascript/provision-infrastructure.jsFile:
docs/api/examples/python/provision-infrastructure.pySwagger UI Integration
File:
resources/views/api/documentation.blade.phpRoute: Add to
routes/web.phpImplementation Approach
Step 1: Enhance OpenAPI Specification (2-3 hours)
Step 2: Write Core Documentation Files (4-5 hours)
docs/api/README.mdlanding pageauthentication.mdwith step-by-step token generationrate-limiting.mdwith tier comparison and retry strategiesorganizations.md,white-label.md, etc.)webhooks.mdwith HMAC validation exampleserrors.mdreference with all status codesStep 3: Create Code Examples (3-4 hours)
Step 4: Swagger UI Integration (1-2 hours)
/api/documentationand/api/openapi.jsonStep 5: Additional Resources (2-3 hours)
Step 6: Documentation Site Setup (Optional, 2-3 hours)
Step 7: Review and Testing (1-2 hours)
Step 8: Publish and Maintain (1 hour)
Test Strategy
Documentation Quality Tests
Manual Testing Checklist:
Automated Tests
File:
tests/Feature/Documentation/ApiDocumentationTest.phpIntegration Tests
File:
tests/Feature/Documentation/CodeExamplesTest.phpDefinition of Done
/api/documentationRelated Tasks