Marketplace API Documentation
Complete API reference for all marketplace endpoints in the ATOM SaaS platform.
Table of Contents
- Overview
- Authentication
- Skill Marketplace
- Agent Marketplace
- Domain Marketplace
- Canvas Component Marketplace
- Workflow Marketplace
- Private Marketplace
- Error Codes
Overview
The marketplace system provides multiple marketplaces for different types of assets:
- Skill Marketplace: Share and discover agent skills
- Agent Marketplace: Publish and install agent templates
- Domain Marketplace: Share specialist domains
- Canvas Component Marketplace: UI components and canvases
- Workflow Marketplace: Workflow templates and blueprints
- Private Marketplace: Tenant-specific skill management
All marketplace endpoints support:
- Search and filtering
- Rating and reviews
- Version management
- Approval workflows
- Installation tracking
Authentication
Most marketplace endpoints require authentication. The platform supports multiple authentication methods:
API Key Authentication
X-API-Key: your-api-key-here
OAuth Bearer Token
Authorization: Bearer your-access-token
Session Authentication
For web-based requests, session cookies are automatically handled.
Skill Marketplace
Base URL: /api/skills
Browse Marketplace
GET /api/skills/marketplace
Browse and search for skills in the marketplace.
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | - | Search term |
| category | string | No | - | Filter by category |
| tags | string | No | - | Comma-separated tags |
| skill_type | string | No | - | Filter by type (api, function, script, docker, container) |
| sort_by | string | No | popularity | Sort field |
| limit | integer | No | 50 | Max results |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "success": true, "skills": [ { "id": "skill-uuid-123", "name": "Data Analysis Skill", "description": "Advanced data analysis with Python", "category": "productivity", "skill_type": "script", "price": 0.0, "rating": 4.5, "rating_count": 42, "installs": 156, "tags": ["python", "data", "analysis"], "is_approved": true, "created_at": "2026-04-01T12:00:00Z" } ] }
Authentication: Required (SKILL_VIEW permission)
Publish Skill
POST /api/skills/publish
Publish a private skill to the marketplace.
Request Body:
{ "skill_id": "skill-uuid-123", "price": 0.0, "category": "productivity", "tags": ["python", "data"], "long_description": "Full description here...", "documentation_url": "https://docs.example.com/skill" }
Response:
{ "success": true, "marketplace_id": "marketplace-uuid-456", "status": "pending_approval", "message": "Skill submitted for marketplace review" }
Authentication: Required (SKILL_MANAGE permission)
Approve Skill (Admin)
POST /api/skills/approve/{marketplace_id}
Approve a skill for marketplace availability.
Path Parameters:
marketplace_id(string): Marketplace listing ID
Response:
{ "success": true, "marketplace_id": "marketplace-uuid-456", "status": "approved", "approved_at": "2026-04-05T12:00:00Z" }
Authentication: Required (GOVERNANCE_APPROVE permission)
Reject Skill (Admin)
POST /api/skills/reject/{marketplace_id}
Reject a marketplace submission.
Path Parameters:
marketplace_id(string): Marketplace listing ID
Query Parameters:
reason(string): Rejection reason
Response:
{ "success": true, "marketplace_id": "marketplace-uuid-456", "status": "rejected", "reason": "Does not meet quality standards" }
Authentication: Required (GOVERNANCE_APPROVE permission)
Install Skill
POST /api/skills/install
Install a marketplace skill into your tenant.
Request Body:
{ "skill_id": "marketplace-uuid-456", "agent_id": "agent-uuid-789", "config_overrides": { "timeout": 30 } }
Response:
{ "success": true, "skill_id": "installed-skill-uuid-999", "status": "installed", "message": "Skill installed successfully" }
Authentication: Required (SKILL_MANAGE permission)
Rate Skill
POST /api/skills/rate/{marketplace_id}
Rate and review a marketplace skill.
Path Parameters:
marketplace_id(string): Marketplace listing ID
Request Body:
{ "rating": 5, "review": "Excellent skill, saved me hours of work!" }
Response:
{ "success": true, "rating": 5, "new_average": 4.7, "total_ratings": 43 }
Authentication: Required (SKILL_VIEW permission)
Create Skill Version
POST /api/skills/version
Create a frozen version of a skill.
Query Parameters:
skill_id(string): Skill IDversion_name(string): Version name (e.g., "v1.0.0")description(string): Optional description
Response:
{ "success": true, "version_id": "version-uuid-123", "version_name": "v1.0.0" }
Authentication: Required (SKILL_MANAGE permission)
Get Version History
GET /api/skills/history/{skill_id}
Get the version history for a skill.
Path Parameters:
skill_id(string): Skill ID
Response:
{ "success": true, "history": [ { "version_id": "version-uuid-123", "version_name": "v1.0.0", "description": "Initial release", "created_at": "2026-04-01T12:00:00Z" } ] }
Authentication: Required (SKILL_VIEW permission)
Rollback Skill
POST /api/skills/rollback/{skill_id}
Rollback a skill to a previous version.
Path Parameters:
skill_id(string): Skill ID
Query Parameters:
version_id(string): Target version ID
Response:
{ "success": true, "message": "Skill skill-uuid-123 rolled back to version version-uuid-456" }
Authentication: Required (SKILL_MANAGE permission)
Agent Marketplace
Base URL: /api/agent-marketplace
Browse Agents
GET /api/agent-marketplace/browse
Browse available agent templates.
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| limit | integer | No | 50 | Max results |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "agents": [ { "id": "agent-template-uuid-123", "name": "Sales Assistant", "description": "Automated sales follow-up agent", "category": "sales", "price": 19.99, "rating": 4.8, "installs": 234, "version": "1.2.0" } ], "total": 150, "limit": 50, "offset": 0 }
Authentication: Required (Session auth)
Publish Agent
POST /api/agent-marketplace/publish/{agent_id}
Publish an agent to the marketplace.
Path Parameters:
agent_id(string): Agent ID to publish
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Agent name |
| description | string | Yes | Agent description |
| price | float | No | Price (default: 0.0) |
| category | string | No | Category |
Response:
{ "success": true, "template_id": "agent-template-uuid-456", "status": "pending_approval", "message": "Agent submitted for marketplace review" }
Authentication: Required (Session auth)
Install Agent
POST /api/agent-marketplace/install/{template_id}
Install an agent template from the marketplace.
Path Parameters:
template_id(string): Template ID to install
Response:
{ "success": true, "agent_id": "installed-agent-uuid-789", "status": "installed", "message": "Agent installed successfully" }
Authentication: Required (Session auth)
Domain Marketplace
Base URL: /api/v1/domains/marketplace
Submit Domain
POST /api/v1/domains/marketplace/submit
Submit a domain to the marketplace.
Request Body:
{ "domain_id": "domain-uuid-123", "price_usd": 29.99, "license_type": "MIT", "tags": ["sales", "crm", "automation"] }
Response:
{ "success": true, "domain_id": "domain-uuid-123", "status": "pending_approval", "price_usd": 29.99, "license_type": "MIT" }
Authentication: Required (Tenant context)
List My Submissions
GET /api/v1/domains/marketplace/my-submissions
List domains submitted by current tenant.
Response:
[ { "domain_id": "domain-uuid-123", "domain_name": "Sales Automation", "status": "approved", "price_usd": 29.99, "install_count": 45, "rating_average": 4.7 } ]
Authentication: Required (Tenant context)
Approve Domain (Admin)
POST /api/v1/domains/marketplace/{domain_id}/approve
Approve a domain for marketplace.
Path Parameters:
domain_id(string): Domain ID
Response:
{ "success": true, "domain_id": "domain-uuid-123", "status": "approved" }
Authentication: Required (Tenant context, TODO: Admin check)
Reject Domain (Admin)
POST /api/v1/domains/marketplace/{domain_id}/reject
Reject a domain submission.
Path Parameters:
domain_id(string): Domain ID
Query Parameters:
reason(string): Rejection reason
Response:
{ "success": true, "domain_id": "domain-uuid-123", "status": "rejected", "reason": "Does not meet quality standards" }
Authentication: Required (Tenant context, TODO: Admin check)
Search Marketplace
GET /api/v1/domains/marketplace/search
Search marketplace for domains.
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| q | string | No | - | Search query |
| category | string | No | - | Filter by category |
| tags | string | No | - | Comma-separated tags |
| max_price | float | No | - | Maximum price |
| limit | integer | No | 20 | Max results (1-100) |
Response:
[ { "id": "domain-uuid-123", "domain_name": "Sales Automation", "domain_slug": "sales-automation", "description": "Advanced sales workflows", "category": "sales", "price_usd": 29.99, "license_type": "MIT", "tags": ["sales", "crm", "automation"], "install_count": 45, "rating_average": 4.7, "rating_count": 12, "publisher_tenant_id": "tenant-uuid-789" } ]
Authentication: None required
Get Trending Domains
GET /api/v1/domains/marketplace/trending
Get trending domains by install count.
Query Parameters:
limit(integer): Max results (1-50, default: 10)
Response:
[ { "id": "domain-uuid-123", "domain_name": "Sales Automation", "install_count": 156, "rating_average": 4.7 } ]
Authentication: None required
Get Marketplace Stats
GET /api/v1/domains/marketplace/stats
Get marketplace statistics.
Response:
{ "total_domains": 234, "approved_domains": 189, "pending_domains": 45, "total_installs": 5678 }
Authentication: None required
Install Domain
POST /api/v1/domains/marketplace/install
Install a domain template from marketplace.
Request Body:
{ "template_domain_id": "domain-uuid-123", "custom_name": "My Sales Domain" }
Response:
{ "success": true, "domain_id": "installed-domain-uuid-456", "domain_name": "My Sales Domain", "template_id": "domain-uuid-123" }
Authentication: Required (Tenant context)
Rate Domain
POST /api/v1/domains/marketplace/{domain_id}/rate
Rate a domain in the marketplace.
Path Parameters:
domain_id(string): Domain ID
Request Body:
{ "rating": 4.5 }
Response:
{ "success": true, "domain_id": "domain-uuid-123", "rating": 4.5, "new_average": 4.6, "total_ratings": 13 }
Authentication: Required (Tenant context)
Get Domain Details
GET /api/v1/domains/marketplace/{domain_id}
Get detailed information about a marketplace domain.
Path Parameters:
domain_id(string): Domain ID
Response:
{ "id": "domain-uuid-123", "domain_name": "Sales Automation", "domain_slug": "sales-automation", "description": "Advanced sales workflows", "category": "sales", "price_usd": 29.99, "license_type": "MIT", "tags": ["sales", "crm", "automation"], "install_count": 45, "rating_average": 4.7, "rating_count": 12, "publisher_tenant_id": "tenant-uuid-789" }
Authentication: None required
Canvas Component Marketplace
Base URL: /api/components (legacy) or /api/canvas-marketplace (preferred)
Browse Components
GET /api/canvas-marketplace/components
Browse marketplace components.
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | - | Search query |
| category | string | No | - | Filter by category |
| tags | string | No | - | Comma-separated tags |
| component_type | string | No | - | Filter by type |
| min_price | float | No | - | Minimum price |
| max_price | float | No | - | Maximum price |
| is_free | boolean | No | false | Free only |
| is_featured | boolean | No | false | Featured only |
| sort_by | string | No | created_at | Sort field |
| sort_order | string | No | desc | Sort order (asc/desc) |
| limit | integer | No | 50 | Max results (max 100) |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "components": [ { "id": "component-uuid-123", "name": "Data Table", "description": "Interactive data table component", "category": "ui", "component_type": "component", "tags": ["table", "data", "ui"], "version": "1.0.0", "thumbnail_url": "https://cdn.example.com/thumb.png", "price": 0.0, "is_free": true, "is_featured": true, "license": "MIT", "installs": 234, "rating": 4.7, "rating_count": 45, "created_at": "2026-04-01T12:00:00Z", "updated_at": "2026-04-05T12:00:00Z" } ], "total": 150, "limit": 50, "offset": 0, "has_more": true }
Authentication: None required (optional for rate limits)
Get Component Details
GET /api/canvas-marketplace/components/{component_id}
Get detailed component information including code and config.
Path Parameters:
component_id(string): Component ID
Response:
{ "id": "component-uuid-123", "name": "Data Table", "description": "Interactive data table component", "category": "ui", "component_type": "component", "tags": ["table", "data", "ui"], "version": "1.0.0", "code": "export function DataTable({ data }) { ... }", "config_schema": { "type": "object", "properties": { "data": { "type": "array" } } }, "dependencies": ["react", "lodash"], "css_dependencies": ["bootstrap"], "thumbnail_url": "https://cdn.example.com/thumb.png", "preview_url": "https://cdn.example.com/preview.png", "demo_url": "https://demo.example.com", "price": 0.0, "is_free": true, "is_featured": true, "license": "MIT", "installs": 234, "rating": 4.7, "rating_count": 45, "recent_ratings": [ { "id": "rating-uuid-456", "rating": 5, "review": "Great component!", "helpful_count": 12, "created_at": "2026-04-05T12:00:00Z" } ], "created_at": "2026-04-01T12:00:00Z", "updated_at": "2026-04-05T12:00:00Z" }
Authentication: None required
Publish Component
POST /api/canvas-marketplace/components/publish
Submit a component for marketplace review.
Request Body:
{ "component_id": "component-uuid-123", "price": 0.0, "license": "MIT", "tags": ["table", "data", "ui"] }
Response:
{ "status": "submitted_for_approval", "component_id": "component-uuid-123", "message": "Component submitted for marketplace review. You will be notified once approved." }
Authentication: Required (Session auth)
Approve Component (Admin)
POST /api/canvas-marketplace/components/{component_id}/approve
Approve a component for the marketplace.
Path Parameters:
component_id(string): Component ID
Response:
{ "status": "approved", "component_id": "component-uuid-123" }
Authentication: Required (SUPER_ADMIN, ADMIN, or OWNER role)
Reject Component (Admin)
POST /api/canvas-marketplace/components/{component_id}/reject
Reject a component from the marketplace.
Path Parameters:
component_id(string): Component ID
Query Parameters:
reason(string): Rejection reason
Response:
{ "status": "rejected", "component_id": "component-uuid-123", "reason": "Does not meet quality standards" }
Authentication: Required (SUPER_ADMIN, ADMIN, or OWNER role)
Install Component
POST /api/canvas-marketplace/components/install
Install a marketplace component to tenant's canvas.
Request Body:
{ "component_id": "component-uuid-123", "canvas_id": "canvas-uuid-456" }
Response:
{ "status": "installed", "component_id": "component-uuid-123", "canvas_id": "canvas-uuid-456", "message": "Component installed successfully" }
Authentication: Required (Session auth)
Rate Component
POST /api/canvas-marketplace/components/{component_id}/rate
Rate and review a marketplace component.
Path Parameters:
component_id(string): Component ID
Request Body:
{ "rating": 5, "review": "Excellent component!" }
Response:
{ "status": "rated", "component_id": "component-uuid-123", "rating": 5, "aggregate_rating": 4.7 }
Authentication: Required (Session auth)
Get Component Ratings
GET /api/canvas-marketplace/components/{component_id}/ratings
Get ratings and reviews for a component.
Path Parameters:
component_id(string): Component ID
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| limit | integer | No | 20 | Max ratings (max 100) |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "ratings": [ { "id": "rating-uuid-456", "rating": 5, "review": "Great component!", "helpful_count": 12, "not_helpful_count": 0, "author_response": "Thank you!", "author_response_at": "2026-04-06T12:00:00Z", "created_at": "2026-04-05T12:00:00Z" } ], "total": 45, "limit": 20, "offset": 0 }
Authentication: None required
List Categories
GET /api/canvas-marketplace/categories
List all component categories with counts.
Response:
{ "categories": [ { "name": "ui", "count": 45 }, { "name": "charts", "count": 23 } ] }
Authentication: None required
List Tags
GET /api/canvas-marketplace/tags
List all popular tags.
Response:
{ "tags": [ { "name": "table", "count": 42 }, { "name": "data", "count": 35 } ] }
Authentication: None required
Workflow Marketplace
Base URL: /api/marketplace
Get Templates
GET /api/marketplace/templates
Get workflow templates with filtering.
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| category | string | No | - | Filter by category |
| template_type | string | No | - | Filter by type (legacy, advanced, industry) |
| industry | string | No | - | Filter by industry |
| tags | list | No | - | Filter by tags |
Response:
[ { "id": "tmpl_email_summarizer", "name": "Daily Email Summarizer", "description": "Summarize unread emails from Gmail and send digest to Slack", "category": "Productivity", "author": "ATOM Team", "version": "1.0.0", "integrations": ["gmail", "slack", "openai"], "complexity": "Beginner", "tags": ["email", "automation"], "estimated_duration": 300, "multi_step_support": true, "pause_resume_support": false, "downloads": 156, "rating": 4.5, "template_type": "legacy", "created_at": "2026-04-01T12:00:00Z" } ]
Authentication: None required
Get Template Types
GET /api/marketplace/templates/types
Get available template types.
Response:
{ "template_types": [ { "value": "legacy", "label": "Legacy", "description": "Legacy workflow templates" }, { "value": "advanced", "label": "Advanced", "description": "Advanced workflow templates" }, { "value": "industry", "label": "Industry", "description": "Industry workflow templates" } ] }
Authentication: None required
Get Featured Templates
GET /api/marketplace/templates/featured
Get featured templates.
Query Parameters:
limit(integer): Max results (1-50, default: 10)
Response:
[ { "id": "tmpl_email_summarizer", "name": "Daily Email Summarizer", "rating": 4.5, "downloads": 156, "is_featured": true } ]
Authentication: None required
Get Template Details
GET /api/marketplace/templates/{template_id}
Get a specific template by ID.
Path Parameters:
template_id(string): Template ID
Response:
{ "id": "tmpl_email_summarizer", "name": "Daily Email Summarizer", "description": "Summarize unread emails from Gmail", "category": "Productivity", "author": "ATOM Team", "version": "1.0.0", "integrations": ["gmail", "slack", "openai"], "complexity": "Beginner", "workflow_data": { "nodes": [ { "id": "1", "type": "trigger", "label": "Every Morning", "config": {"cron": "0 9 * * *"} } ], "edges": [ {"source": "1", "target": "2"} ] }, "downloads": 156, "rating": 4.5, "tags": ["email", "automation"] }
Authentication: None required
Import Template
POST /api/marketplace/templates/{template_id}/import
Import a template into your workspace.
Path Parameters:
template_id(string): Template ID
Response:
{ "id": "workflow-uuid-789", "name": "Imported: Daily Email Summarizer", "nodes": [...], "edges": [...], "imported_at": "2026-04-05T12:00:00Z" }
Authentication: None required
Create Advanced Template
POST /api/marketplace/templates/advanced
Create a new advanced workflow template.
Request Body:
{ "id": "advanced_custom_workflow", "name": "Custom Advanced Workflow", "description": "My custom workflow", "category": "Custom", "author": "Your Name", "version": "1.0.0", "integrations": ["slack", "email"], "complexity": "Intermediate", "tags": ["custom", "automation"], "input_schema": [ { "name": "data_source", "type": "select", "label": "Data Source", "required": true } ], "steps": [ { "step_id": "validate", "name": "Validate Inputs", "step_type": "validation", "estimated_duration": 30 } ], "estimated_duration": 300, "prerequisites": ["api_access"], "use_cases": ["Data processing"], "benefits": ["Automation", "Efficiency"] }
Response:
{ "id": "advanced_custom_workflow", "name": "Custom Advanced Workflow", "input_schema": [...], "steps": [...], "estimated_duration": 300, "created_at": "2026-04-05T12:00:00Z" }
Authentication: None required
Create Workflow from Template
POST /api/marketplace/templates/{template_id}/create-workflow
Create a workflow from an advanced template.
Path Parameters:
template_id(string): Template ID
Query Parameters:
workflow_name(string): Workflow nameparameters(object): User inputs (JSON)
Response:
{ "status": "success", "workflow_definition": { "workflow_id": "workflow-uuid-789", "name": "My Workflow", "category": "Data Processing", "input_schema": [...], "steps": [...], "user_inputs": {...} }, "message": "Workflow 'My Workflow' created successfully from template tmpl_email_summarizer" }
Authentication: None required
Import Workflow (File)
POST /api/marketplace/import
Import a workflow from a JSON file.
Request Body (multipart/form-data):
file: Workflow JSON file
Response:
{ "id": "workflow-uuid-789", "name": "Imported: My Workflow", "nodes": [...], "edges": [...], "imported_at": "2026-04-05T12:00:00Z" }
Authentication: None required
Export Workflow
POST /api/marketplace/export
Export a workflow to JSON format.
Request Body:
{ "name": "My Workflow", "description": "My custom workflow", "nodes": [...], "edges": [...] }
Response:
{ "name": "My Workflow", "description": "My custom workflow", "nodes": [...], "edges": [...], "metadata": { "exported_at": "2026-04-05T12:00:00Z", "version": "1.0.0" } }
Authentication: None required
Get Template Statistics
GET /api/marketplace/templates/statistics
Get marketplace statistics.
Response:
{ "total_templates": 50, "total_downloads": 1234, "average_rating": 4.5, "categories": { "Productivity": {"count": 20, "downloads": 500}, "Sales": {"count": 15, "downloads": 400} }, "template_types": { "legacy": {"count": 30, "downloads": 600}, "advanced": {"count": 15, "downloads": 500}, "industry": {"count": 5, "downloads": 134} }, "complexity_levels": { "Beginner": {"count": 20, "downloads": 400}, "Intermediate": {"count": 20, "downloads": 500}, "Advanced": {"count": 10, "downloads": 334} } }
Authentication: None required
Private Marketplace
Base URL: /api/v1/skills
List Private Skills
GET /api/v1/skills/private
List tenant's private skills (created + installed).
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | - | Search term |
| category | string | No | - | Filter by category |
| skill_type | string | No | - | Filter by type |
| is_installed | boolean | No | - | Filter by installation status |
| sort_by | string | No | name | Sort field |
| sort_order | string | No | asc | Sort order (asc/desc) |
| limit | integer | No | 50 | Max results |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "success": true, "skills": [ { "id": "skill-uuid-123", "name": "My Custom Skill", "description": "Custom skill for my workflow", "skill_type": "function", "category": "productivity", "is_own": true, "is_installed": false, "rating": 4.5, "created_at": "2026-04-01T12:00:00Z" } ], "total": 25, "limit": 50, "offset": 0 }
Authentication: Required (SKILL_VIEW permission)
Install from Marketplace
POST /api/v1/skills/private/install
Install a marketplace skill to private marketplace.
Request Body:
{ "marketplace_skill_id": "marketplace-skill-uuid-123", "agent_id": "agent-uuid-456", "config_overrides": { "timeout": 60 } }
Response:
{ "success": true, "skill_id": "installed-skill-uuid-789", "status": "installed", "message": "Skill installed successfully", "packages_installed": [ { "package_name": "requests", "package_type": "python", "status": "installed" } ] }
Authentication: Required (SKILL_MANAGE permission)
Customize Skill
PUT /api/v1/skills/private/{skill_id}
Customize an installed private skill.
Path Parameters:
skill_id(string): Skill ID
Request Body:
{ "name": "My Custom Name", "description": "My custom description", "config_overrides": { "timeout": 60 }, "environment_vars": { "API_KEY": "custom-key" } }
Response:
{ "success": true, "skill_id": "skill-uuid-123", "name": "My Custom Name", "description": "My custom description", "config_overrides_applied": true }
Authentication: Required (SKILL_MANAGE permission)
Uninstall Skill
DELETE /api/v1/skills/private/{skill_id}
Uninstall a marketplace skill from private marketplace.
Path Parameters:
skill_id(string): Skill ID
Response:
{ "success": true, "skill_id": "skill-uuid-123", "status": "uninstalled", "message": "Skill uninstalled successfully" }
Authentication: Required (SKILL_MANAGE permission)
Create Private Skill
POST /api/v1/skills/private
Create a completely private skill (not shared to marketplace).
Request Body:
{ "name": "My Private Skill", "description": "Internal skill only", "skill_type": "function", "input_schema": { "type": "object", "properties": { "data": {"type": "string"} } }, "output_schema": { "type": "object", "properties": { "result": {"type": "string"} } }, "config": { "timeout": 30 }, "code": "def execute(data): return {'result': data}", "category": "productivity", "tags": ["internal", "custom"] }
Response:
{ "success": true, "skill_id": "skill-uuid-123", "name": "My Private Skill", "status": "created", "is_public": false }
Authentication: Required (SKILL_MANAGE permission)
Public Marketplace API
Base URL: /api/public/v1/marketplace
Browse Public Skills
GET /api/public/v1/marketplace/skills
Browse the public skill marketplace (read-only API).
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | - | Search term |
| category | string | No | - | Filter by category |
| tags | string | No | - | Comma-separated tags |
| skill_type | string | No | - | Filter by type |
| is_free | boolean | No | false | Free only |
| is_featured | boolean | No | false | Featured only |
| sort_by | string | No | created_at | Sort field |
| sort_order | string | No | desc | Sort order (asc/desc) |
| limit | integer | No | 50 | Max results (max 100) |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "skills": [ { "id": "skill-uuid-123", "name": "Data Analysis", "description": "Advanced data analysis", "category": "productivity", "skill_type": "script", "price": 0.0, "is_free": true, "rating": 4.5, "rating_count": 42, "installs": 156, "tags": ["python", "data"], "created_at": "2026-04-01T12:00:00Z" } ], "total": 150, "limit": 50, "offset": 0, "has_more": true }
Authentication: Optional (higher rate limits with auth)
Get Public Skill Details
GET /api/public/v1/marketplace/skills/{skill_id}
Get detailed information about a specific marketplace skill.
Path Parameters:
skill_id(string): Skill ID
Response:
{ "id": "skill-uuid-123", "name": "Data Analysis", "description": "Advanced data analysis with Python", "long_description": "Full documentation...", "category": "productivity", "skill_type": "script", "input_schema": {...}, "output_schema": {...}, "config": {...}, "price": 0.0, "is_free": true, "rating": 4.5, "rating_count": 42, "installs": 156, "tags": ["python", "data"], "license": "MIT", "documentation_url": "https://docs.example.com", "repository_url": "https://github.com/example/skill", "python_packages": [{"name": "pandas", "version": "2.0.0"}], "npm_packages": [], "recent_reviews": [ { "rating": 5, "review": "Excellent!", "created_at": "2026-04-05T12:00:00Z" } ], "created_at": "2026-04-01T12:00:00Z" }
Authentication: Optional
Get Categories
GET /api/public/v1/marketplace/categories
Get all skill categories.
Response:
{ "categories": ["productivity", "sales", "finance", "communication"] }
Authentication: Optional
Get Tags
GET /api/public/v1/marketplace/tags
Get all skill tags with usage counts.
Response:
{ "tags": [ {"name": "python", "count": 42}, {"name": "api", "count": 35}, {"name": "data", "count": 28} ] }
Authentication: Optional
Submit Skill (Public API)
POST /api/public/v1/marketplace/submit
Submit a skill for the marketplace (requires authentication).
Request Body:
{ "name": "My Skill", "description": "Skill description", "skill_type": "function", "input_schema": {...}, "output_schema": {...}, "config": {...}, "code": "...", "long_description": "Full documentation...", "category": "productivity", "tags": ["python", "data"], "price": 0.0, "license": "MIT", "documentation_url": "https://docs.example.com", "repository_url": "https://github.com/example/skill", "python_packages": [{"name": "requests", "version": "2.28.0"}], "npm_packages": [] }
Response:
{ "success": true, "skill_id": "skill-uuid-123", "status": "pending_approval", "message": "Skill submitted for marketplace review" }
Authentication: Required (API key or OAuth token)
Rate Skill (Public API)
POST /api/public/v1/marketplace/skills/{skill_id}/rate
Rate a marketplace skill (requires authentication).
Path Parameters:
skill_id(string): Skill ID
Request Body:
{ "rating": 5, "review": "Excellent skill!" }
Response:
{ "success": true, "rating": 5, "new_average": 4.7, "total_ratings": 43 }
Authentication: Required (API key or OAuth token)
Get Reviews
GET /api/public/v1/marketplace/skills/{skill_id}/reviews
Get reviews for a skill (no authentication required).
Path Parameters:
skill_id(string): Skill ID
Query Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| limit | integer | No | 20 | Max reviews (1-100) |
| offset | integer | No | 0 | Pagination offset |
Response:
{ "reviews": [ { "id": "review-uuid-456", "rating": 5, "review": "Excellent skill!", "created_at": "2026-04-05T12:00:00Z", "helpful_count": 12 } ], "total": 42, "limit": 20, "offset": 0 }
Authentication: None required
Flag Review
POST /api/public/v1/marketplace/reviews/{review_id}/flag
Flag a review for moderation (requires authentication).
Path Parameters:
review_id(string): Review ID
Query Parameters:
reason(string): Flag reason (1-500 chars)
Response:
{ "success": true, "review_id": "review-uuid-456", "status": "flagged" }
Authentication: Required (API key or OAuth token)
Error Codes
HTTP Status Codes
| Status | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 429 | Rate Limit Exceeded |
| 500 | Internal Server Error |
Error Response Format
All error responses follow this format:
{ "error": "Error type", "message": "Detailed error message", "code": "ERROR_CODE", "details": { "field": "Additional context" } }
Common Error Scenarios
Authentication Errors
401 Unauthorized
{ "error": "Unauthorized", "message": "Authentication required. Use X-API-Key or Authorization: Bearer header.", "code": "AUTH_REQUIRED" }
401 Invalid API Key
{ "error": "Unauthorized", "message": "Invalid or inactive API key", "code": "INVALID_API_KEY" }
401 Expired Token
{ "error": "Unauthorized", "message": "Invalid or expired OAuth token", "code": "EXPIRED_TOKEN" }
Permission Errors
403 Forbidden
{ "error": "Forbidden", "message": "Read-only key cannot perform write operations", "code": "INSUFFICIENT_SCOPE" }
403 Governance Denied
{ "error": "Forbidden", "message": "Agent maturity level insufficient for this action", "code": "GOVERNANCE_DENIED" }
Validation Errors
400 Bad Request
{ "error": "Bad Request", "message": "Validation failed", "code": "VALIDATION_ERROR", "details": { "field": "skill_type", "message": "Invalid skill type. Must be one of: api, function, script, docker, container" } }
400 Invalid Input
{ "error": "Bad Request", "message": "Maximum limit is 100", "code": "INVALID_LIMIT" }
Not Found Errors
404 Not Found
{ "error": "Not Found", "message": "Skill not found or not approved", "code": "SKILL_NOT_FOUND" }
404 Component Not Found
{ "error": "Not Found", "message": "Component not found", "code": "COMPONENT_NOT_FOUND" }
Rate Limiting
429 Rate Limit Exceeded
{ "error": "Rate Limit Exceeded", "message": "Rate limit exceeded. Please try again later.", "code": "RATE_LIMIT_EXCEEDED", "retry_after": 60 }
Headers:
Retry-After: 60
Server Errors
500 Internal Server Error
{ "error": "Internal Server Error", "message": "An unexpected error occurred", "code": "INTERNAL_ERROR" }
Marketplace-Specific Error Codes
| Code | HTTP Status | Description |
|---|---|---|
| SKILL_NOT_FOUND | 404 | Skill not found or not approved |
| COMPONENT_NOT_FOUND | 404 | Component not found |
| TEMPLATE_NOT_FOUND | 404 | Template not found |
| DOMAIN_NOT_FOUND | 404 | Domain not found |
| AGENT_NOT_FOUND | 404 | Agent template not found |
| ALREADY_PUBLISHED | 409 | Item already published |
| PENDING_APPROVAL | 403 | Item is pending approval |
| APPROVAL_REQUIRED | 403 | Item requires admin approval |
| NOT_OWNER | 403 | User does not own this item |
| INSTALL_FAILED | 422 | Installation failed |
| PACKAGE_INSTALL_FAILED | 422 | Package installation failed |
| INVALID_VERSION | 400 | Invalid version format |
| RATING_EXISTS | 409 | User has already rated this item |
| TENANT_NOT_FOUND | 404 | Tenant context not found |
| TENANT_LIMIT_EXCEEDED | 429 | Tenant quota limit exceeded |
| AGENT_LIMIT_EXCEEDED | 429 | Agent count limit exceeded |
| SKILL_LIMIT_EXCEEDED | 429 | Skill count limit exceeded |
| PACKAGE_NOT_WHITELISTED | 403 | Package not in whitelist |
| PACKAGE_VULNERABILITY | 403 | Package has security vulnerabilities |
| DEPENDENCY_MISSING | 422 | Required dependency missing |
| CONFIG_SCHEMA_INVALID | 400 | Configuration schema invalid |
| INPUT_VALIDATION_FAILED | 400 | Input validation failed |
| MISSING_REQUIRED_FIELD | 400 | Required field missing |
| INVALID_ENUM_VALUE | 400 | Invalid enum value provided |
| DUPLICATE_ENTRY | 409 | Duplicate entry detected |
| CONFLICTING_OPERATION | 409 | Conflicting operation in progress |
| SERVICE_UNAVAILABLE | 503 | Service temporarily unavailable |
| MAINTENANCE_MODE | 503 | System under maintenance |
| MARKETPLACE_DISABLED | 503 | Marketplace feature disabled |
Advanced Error Scenarios
Tenant Quota Errors
429 Too Many Requests - Tenant Agent Limit
{ "error": "Quota Exceeded", "message": "Tenant has reached maximum agent limit (10). Upgrade to Team plan for 25 agents.", "code": "AGENT_LIMIT_EXCEEDED", "details": { "current": 10, "limit": 10, "plan": "Free", "upgrade_url": "https://atom-saas.fly.dev/settings/billing" } }
Solution: Upgrade plan or delete unused agents
429 Too Many Requests - Daily Skill Execution Limit
{ "error": "Quota Exceeded", "message": "Daily skill execution limit reached (50/50). Resets at midnight UTC.", "code": "SKILL_LIMIT_EXCEEDED", "details": { "current": 50, "limit": 50, "resets_at": "2026-04-06T00:00:00Z" } }
Solution: Wait for daily reset or upgrade plan
Package Installation Errors
403 Forbidden - Package Not Whitelisted
{ "error": "Forbidden", "message": "Package 'malicious-package' is not whitelisted. Contact administrator to request approval.", "code": "PACKAGE_NOT_WHITELISTED", "details": { "package_name": "malicious-package", "package_type": "python", "request_url": "https://atom-saas.fly.dev/admin/packages/request" } }
Solution: Request package whitelisting from admin
403 Forbidden - Package Vulnerability Detected
{ "error": "Forbidden", "message": "Package 'old-package' has 2 known security vulnerabilities. Update to version 2.0.0 or later.", "code": "PACKAGE_VULNERABILITY", "details": { "package_name": "old-package", "current_version": "1.5.0", "safe_version": "2.0.0", "vulnerabilities": [ { "severity": "HIGH", "cve": "CVE-2024-12345", "description": "Remote code execution vulnerability" } ] } }
Solution: Update package to safe version
422 Unprocessable Entity - Dependency Missing
{ "error": "Installation Failed", "message": "Required dependency 'pandas' is not installed. Install it first.", "code": "DEPENDENCY_MISSING", "details": { "missing_package": "pandas", "required_by": "data-analysis-skill", "install_command": "pip install pandas>=2.0.0" } }
Solution: Install missing dependency
Governance Errors
403 Forbidden - Agent Maturity Insufficient
{ "error": "Governance Denied", "message": "Agent maturity 'student' cannot perform action 'send_email'. Required maturity: 'supervised'.", "code": "GOVERNANCE_DENIED", "details": { "agent_id": "agent-uuid-123", "current_maturity": "student", "required_maturity": "supervised", "action": "send_email", "reason": "Student agents are read-only. Graduate agent to intern for proposal permissions." } }
Solution: Graduate agent to higher maturity level
403 Forbidden - Skill Requires Approval
{ "error": "Approval Required", "message": "Skill 'exec-shell-commands' requires explicit approval due to security risk.", "code": "APPROVAL_REQUIRED", "details": { "skill_id": "skill-uuid-456", "risk_level": "HIGH", "reason": "Can execute arbitrary shell commands", "approval_url": "https://atom-saas.fly.dev/admin/skills/approve" } }
Solution: Request admin approval for high-risk skills
Validation Errors
400 Bad Request - Invalid Configuration Schema
{ "error": "Validation Failed", "message": "Configuration schema does not match skill requirements.", "code": "CONFIG_SCHEMA_INVALID", "details": { "expected_schema": { "type": "object", "properties": { "api_key": {"type": "string"}, "timeout": {"type": "number"} }, "required": ["api_key"] }, "provided_config": { "api_key": "sk-123", "invalid_field": "value" }, "errors": [ "Additional property 'invalid_field' not allowed", "Missing required property 'timeout'" ] } }
Solution: Fix configuration to match schema
400 Bad Request - Invalid Enum Value
{ "error": "Validation Failed", "message": "Invalid value for field 'skill_type'.", "code": "INVALID_ENUM_VALUE", "details": { "field": "skill_type", "provided_value": "webhook", "allowed_values": ["api", "function", "script", "docker", "container"] } }
Solution: Use valid enum value
409 Conflict - Duplicate Entry
{ "error": "Duplicate Entry", "message": "A skill with this name already exists in your private marketplace.", "code": "DUPLICATE_ENTRY", "details": { "field": "name", "value": "Data Analysis", "existing_skill_id": "skill-uuid-789", "suggestion": "Use a different name or update the existing skill" } }
Solution: Use unique name or update existing entry
Service Errors
503 Service Unavailable - Maintenance Mode
{ "error": "Service Unavailable", "message": "Marketplace is under maintenance. Expected downtime: 30 minutes.", "code": "MAINTENANCE_MODE", "details": { "started_at": "2026-04-05T12:00:00Z", "expected_end": "2026-04-05T12:30:00Z", "status_page": "https://status.atomagentos.com" } }
Solution: Wait for maintenance to complete
503 Service Unavailable - Marketplace Disabled
{ "error": "Service Unavailable", "message": "Marketplace feature is disabled for this tenant.", "code": "MARKETPLACE_DISABLED", "details": { "feature": "public_marketplace", "reason": "Enterprise plan required", "upgrade_url": "https://atom-saas.fly.dev/settings/billing" } }
Solution: Upgrade to enable marketplace
Troubleshooting Guide
Authentication Issues
Problem: 401 Unauthorized - No API Key Provided
Symptoms:
{ "error": "Unauthorized", "message": "Authentication required. Use X-API-Key or Authorization: Bearer header.", "code": "AUTH_REQUIRED" }
Diagnosis:
- Missing
X-API-Keyheader - Missing
Authorization: Bearerheader - Session cookie expired
Solutions:
- Add API Key Header:
curl -X GET "https://atom-saas.fly.dev/api/skills/marketplace" \ -H "X-API-Key: sk-your-api-key"
- Add Bearer Token:
curl -X GET "https://atom-saas.fly.dev/api/skills/marketplace" \ -H "Authorization: Bearer your-access-token"
- Check API Key Format:
- Must start with
sk- - Only alphanumeric characters after prefix
- Example:
sk-abc123def456
Problem: 401 Unauthorized - Invalid API Key
Symptoms:
{ "error": "Unauthorized", "message": "Invalid or inactive API key", "code": "INVALID_API_KEY" }
Diagnosis:
- API key doesn't exist in database
- API key is inactive (
is_active=False) - API key has been revoked
Solutions:
-
Verify Key in Dashboard:
- Go to Settings → API Keys
- Check key status is "Active"
- Copy key again (ensure no extra spaces)
-
Generate New Key:
- Delete old key
- Create new key
- Update application with new key
-
Check Key Scope:
# Verify key has correct scope key = db.query(APIKey).filter(key_value="sk-your-key").first() print(f"Scope: {key.scope}") # Should be "read_write" for operations
Problem: 401 Unauthorized - Expired OAuth Token
Symptoms:
{ "error": "Unauthorized", "message": "Invalid or expired OAuth token", "code": "EXPIRED_TOKEN" }
Diagnosis:
- Access token expired (typically 1 hour lifetime)
- Refresh token also expired
- Token revoked by user
Solutions:
- Refresh Access Token:
# Use refresh token to get new access token response = requests.post("https://atom-saas.fly.dev/oauth/token", data={ "grant_type": "refresh_token", "refresh_token": refresh_token }) new_access_token = response.json()["access_token"]
- Re-authenticate User:
# Redirect user to OAuth flow auth_url = f"https://atom-saas.fly.dev/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}" # Redirect user to auth_url
Permission Issues
Problem: 403 Forbidden - Insufficient Scope
Symptoms:
{ "error": "Forbidden", "message": "Read-only key cannot perform write operations", "code": "INSUFFICIENT_SCOPE" }
Diagnosis:
- API key has
readscope - Attempting write operation (POST, PUT, DELETE)
Solutions:
- Check Key Scope:
key = db.query(APIKey).filter(key_value="sk-your-key").first() if key.scope == "read": print("Key is read-only. Need read_write scope.")
-
Create Read-Write Key:
- Delete read-only key
- Create new key with scope="read_write"
-
Use Correct Key:
# Use read_write key for write operations curl -X POST "https://atom-saas.fly.dev/api/skills/publish" \ -H "X-API-Key: sk-read-write-key" \ -H "Content-Type: application/json" \ -d '{"skill_id": "..."}'
Problem: 403 Forbidden - Governance Denied
Symptoms:
{ "error": "Forbidden", "message": "Agent maturity level insufficient for this action", "code": "GOVERNANCE_DENIED" }
Diagnosis:
- Agent maturity too low for action
- Action requires higher maturity level
Maturity Levels:
student: Read-only (browse, search)intern: Proposals (requires approval)supervised: Live monitoring (can act with supervision)autonomous: Full access (can supervise others)
Solutions:
- Graduate Agent:
# Check graduation readiness from core.agent_graduation_service import AgentGraduationService grad_service = AgentGraduationService(db) result = grad_service.check_unified_graduation( agent_id="agent-uuid-123", tenant_id=tenant_id, target_maturity="SUPERVISED" ) if result["ready"]: # Graduate agent grad_service graduate_agent(agent_id, "SUPERVISED")
- Use Higher Maturity Agent:
# Find supervised agent agent = db.query(Agent).filter( Agent.maturity == "supervised", Agent.tenant_id == tenant_id ).first() # Use this agent for the action
Rate Limiting Issues
Problem: 429 Too Many Requests
Symptoms:
HTTP/1.1 429 Too Many Requests Retry-After: 60 { "error": "Rate Limit Exceeded", "message": "Rate limit exceeded. Please try again later.", "code": "RATE_LIMIT_EXCEEDED" }
Diagnosis:
- Exceeded request limit (60-100 req/min depending on auth)
- Too many requests from same IP/API key
Solutions:
- Implement Exponential Backoff:
import time import random def make_request_with_backoff(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code != 429: return response # Exponential backoff: 2^attempt + random jitter wait_time = (2 ** attempt) + random.uniform(0, 1) retry_after = int(response.headers.get("Retry-After", wait_time)) print(f"Rate limited. Waiting {retry_after} seconds...") time.sleep(retry_after) return response # Last attempt
- Cache Responses:
from functools import lru_cache import time @lru_cache(maxsize=100) def get_marketplace_skills(cache_buster=None): """Cache marketplace skills for 5 minutes""" response = requests.get( "https://atom-saas.fly.dev/api/skills/marketplace", headers={"X-API-Key": "sk-your-key"} ) return response.json() # Use cache buster to invalidate cache_key = int(time.time() // 300) # New key every 5 minutes skills = get_marketplace_skills(cache_buster=cache_key)
- Batch Operations:
# Instead of multiple requests for skill_id in skill_ids: response = requests.get(f"/api/skills/{skill_id}") # Bad: N requests # Use single request with IDs response = requests.get("/api/skills", params={"ids": ",".join(skill_ids)}) # Good: 1 request
- Monitor Rate Limit Headers:
response = requests.get(url, headers=headers) # Check rate limit status remaining = int(response.headers.get("X-RateLimit-Remaining", 0)) limit = int(response.headers.get("X-RateLimit-Limit", 60)) if remaining < 10: print(f"Warning: Only {remaining} requests remaining (limit: {limit})") # Slow down requests
Installation Failures
Problem: 422 Unprocessable Entity - Package Not Whitelisted
Symptoms:
{ "error": "Installation Failed", "message": "Package 'malicious-package' is not whitelisted.", "code": "PACKAGE_NOT_WHITELISTED" }
Diagnosis:
- Skill requires package not in whitelist
- Security policy blocks unknown packages
Solutions:
- Request Package Whitelist:
# Submit package for approval curl -X POST "https://atom-saas.fly.dev/api/packages/request" \ -H "X-API-Key: sk-your-key" \ -H "Content-Type: application/json" \ -d '{ "package_name": "data-package", "package_type": "python", "version": "1.0.0", "reason": "Required for data analysis skill" }'
- Use Alternative Package:
# Find whitelisted alternative from core.package_whitelist_service import PackageWhitelistService service = PackageWhitelistService(db) alternatives = service.search_packages( query="data processing", package_type="python" ) print(f"Alternatives: {alternatives}")
- Contact Admin:
- Email: support@atomagentos.com
- Include: package name, version, use case
Problem: 403 Forbidden - Package Vulnerability
Symptoms:
{ "error": "Forbidden", "message": "Package 'old-package' has 2 known security vulnerabilities.", "code": "PACKAGE_VULNERABILITY" }
Diagnosis:
- Package has known CVEs
- Automated security scan detected issues
Solutions:
- Update Package:
# Check for safe version from core.package_installation_service import PackageInstallationService service = PackageInstallationService(db) safe_version = service.get_safe_version("old-package") print(f"Update to version: {safe_version}") # e.g., "2.0.0"
- Modify Skill Requirements:
{ "python_packages": [ { "name": "old-package", "version": "2.0.0", // Updated to safe version "type": "python" } ] }
- Review CVE Details:
# Check vulnerability details curl "https://atom-saas.fly.dev/api/packages/old-package/vulnerabilities" \ -H "X-API-Key: sk-your-key"
Problem: 422 Unprocessable Entity - Dependency Missing
Symptoms:
{ "error": "Installation Failed", "message": "Required dependency 'pandas' is not installed.", "code": "DEPENDENCY_MISSING" }
Diagnosis:
- Skill requires package that isn't installed
- Dependency chain incomplete
Solutions:
- Install Missing Dependency:
from core.package_installation_service import PackageInstallationService service = PackageInstallationService(db) # Install dependency result = await service.install_package( tenant_id=tenant_id, package_name="pandas", package_type="python", version=">=2.0.0" ) print(f"Installation: {result['status']}")
- Install Skill with Dependencies:
# Skill installation should auto-install dependencies curl -X POST "https://atom-saas.fly.dev/api/skills/install" \ -H "X-API-Key: sk-your-key" \ -H "Content-Type: application/json" \ -d '{ "skill_id": "skill-uuid-123", "install_dependencies": true }'
- Verify Dependencies:
# Check installed packages service = PackageInstallationService(db) installed = service.list_installed_packages(tenant_id) print("Installed packages:") for pkg in installed: print(f" - {pkg['name']}: {pkg['version']}")
Validation Errors
Problem: 400 Bad Request - Invalid Configuration
Symptoms:
{ "error": "Validation Failed", "message": "Configuration schema does not match skill requirements.", "code": "CONFIG_SCHEMA_INVALID" }
Diagnosis:
- Config doesn't match skill schema
- Missing required fields
- Invalid data types
Solutions:
- Get Skill Schema:
# Retrieve skill schema first curl -X GET "https://atom-saas.fly.dev/api/skills/skill-uuid-123" \ -H "X-API-Key: sk-your-key" # Response includes config_schema { "config_schema": { "type": "object", "properties": { "api_key": {"type": "string"}, "timeout": {"type": "number", "default": 30} }, "required": ["api_key"] } }
- Match Configuration to Schema:
# Build config matching schema config = { "api_key": "sk-123", # Required "timeout": 60 # Optional, with default } # Validate config before sending from jsonschema import validate validate(instance=config, schema=skill["config_schema"])
- Use Schema Builder:
# Auto-generate config form from schema def build_config_form(schema): form = {} for field_name, field_def in schema["properties"].items(): required = field_name in schema.get("required", []) form[field_name] = { "type": field_def["type"], "required": required, "default": field_def.get("default") } return form form = build_config_form(skill["config_schema"])
Common Mistakes
Mistake 1: Missing Content-Type Header
Wrong:
curl -X POST "https://atom-saas.fly.dev/api/skills/publish" \ -H "X-API-Key: sk-your-key" \ -d '{"skill_id": "..."}'
Correct:
curl -X POST "https://atom-saas.fly.dev/api/skills/publish" \ -H "X-API-Key: sk-your-key" \ -H "Content-Type: application/json" \ -d '{"skill_id": "..."}'
Mistake 2: Wrong API Key for Environment
Problem: Using production key in development
Solution:
import os # Use environment-specific keys if os.environ.get("ENV") == "production": API_KEY = os.environ["PRODUCTION_API_KEY"] BASE_URL = "https://atom-saas.fly.dev" else: API_KEY = os.environ["DEV_API_KEY"] BASE_URL = "https://atom-saas-dev.fly.dev"
Mistake 3: Ignoring Rate Limit Headers
Wrong:
# Doesn't check rate limits while True: response = requests.get(url, headers=headers)
Correct:
# Checks rate limits while True: response = requests.get(url, headers=headers) remaining = int(response.headers.get("X-RateLimit-Remaining", 0)) if remaining == 0: reset_time = int(response.headers.get("X-RateLimit-Reset", 0)) wait_seconds = reset_time - int(time.time()) time.sleep(wait_seconds)
Mistake 4: Not Handling Pagination
Wrong:
# Only gets first page response = requests.get(f"{url}?limit=50") skills = response.json()["skills"]
Correct:
# Gets all pages all_skills = [] offset = 0 limit = 50 while True: response = requests.get(f"{url}?limit={limit}&offset={offset}") data = response.json() all_skills.extend(data["skills"]) if not data["has_more"]: break offset += limit
Mistake 5: Hardcoding IDs
Wrong:
# Hardcoded ID breaks when skill changes skill_id = "skill-uuid-123"
Correct:
# Search for skill by name response = requests.get(f"{url}?query=data%20analysis") skills = response.json()["skills"] if skills: skill_id = skills[0]["id"] # Use actual ID
Debugging Tools
API Test Console
Built-in API explorer for testing endpoints:
# Open API test console open "https://atom-saas.fly.dev/api/test-console"
Features:
- Interactive API testing
- Request/response inspection
- Authentication handling
- Error explanation
Logging
Enable debug logging:
import logging # Enable request logging logging.basicConfig(level=logging.DEBUG) requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True # Make request response = requests.get(url, headers=headers) # Logs show: # DEBUG:urllib3.connectionpool:Starting new HTTPS connection # DEBUG:urllib3.connectionpool:https://atom-saas.fly.dev:443 "GET /api/skills/marketplace HTTP/1.1" 200 1234
Response Inspection
Inspect full response details:
def inspect_response(response): """Print detailed response information.""" print(f"Status: {response.status_code}") print(f"Headers: {dict(response.headers)}") print(f"Body: {response.text}") # Check rate limits if "X-RateLimit-Remaining" in response.headers: remaining = response.headers["X-RateLimit-Remaining"] limit = response.headers["X-RateLimit-Limit"] print(f"Rate Limit: {remaining}/{limit} remaining") # Check for errors try: data = response.json() if "error" in data: print(f"Error Code: {data.get('code')}") print(f"Error Message: {data.get('message')}") if "details" in data: print(f"Details: {data['details']}") except: pass # Use it response = requests.get(url, headers=headers) inspect_response(response)
Monitoring and Alerting
Health Checks
Monitor API health:
# Check API status curl -X GET "https://atom-saas.fly.dev/api/health"
Response:
{ "status": "healthy", "version": "1.0.0", "timestamp": "2026-04-05T12:00:00Z", "services": { "database": "healthy", "redis": "healthy", "marketplace": "healthy" } }
Error Tracking
Track errors over time:
from collections import defaultdict class ErrorTracker: def __init__(self): self.errors = defaultdict(int) def log_error(self, response): if response.status_code >= 400: try: data = response.json() error_code = data.get("code", "UNKNOWN") self.errors[error_code] += 1 except: self.errors["UNKNOWN"] += 1 def get_summary(self): return dict(self.errors) # Use it tracker = ErrorTracker() for i in range(100): response = requests.get(url, headers=headers) tracker.log_error(response) print("Error Summary:") print(tracker.get_summary()) # Output: {"RATE_LIMIT_EXCEEDED": 5, "SKILL_NOT_FOUND": 2}
Troubleshooting Guide
Authentication Issues
- Check API key format: Should be
sk-followed by alphanumeric characters - Verify key is active: Check in admin dashboard
- Check key scope: Read-only keys cannot write
- OAuth token expired: Obtain new token
Permission Issues
- Verify user permissions: Check RBAC settings
- Check agent maturity: Higher maturity required for some actions
- Tenant context required: Some endpoints need tenant context
Rate Limiting
- Default limits: 60-100 requests per minute depending on auth
- Backoff strategy: Implement exponential backoff
- Retry-After header: Use provided retry delay
Installation Failures
- Check dependencies: Verify packages are whitelisted
- Agent maturity: Some skills require minimum maturity
- Config validation: Verify config schema matches
Rate Limiting
Default Limits
- Unauthenticated: 20 requests/minute
- API Key (read): 60 requests/minute
- API Key (read_write): 60 requests/minute
- OAuth Token: 100 requests/minute
- Federation: 100 requests/minute per IP
Rate Limit Headers
All responses include rate limit headers:
X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1775411393
Best Practices
- Check rate limit headers: Monitor remaining quota
- Implement backoff: Exponential backoff on 429
- Use caching: Cache marketplace data locally
- Batch requests: Combine multiple operations when possible
SDK Examples
Python SDK
from atom_saas import MarketplaceClient # Initialize client client = MarketplaceClient(api_key="sk-your-key") # Browse skills skills = client.skills.browse(category="productivity", limit=10) # Install skill result = client.skills.install( skill_id="skill-uuid-123", agent_id="agent-uuid-456" ) # Rate skill client.skills.rate( skill_id="skill-uuid-123", rating=5, review="Excellent!" )
JavaScript SDK
import { MarketplaceClient } from '@atom-saas/sdk'; // Initialize client const client = new MarketplaceClient({ apiKey: 'sk-your-key' }); // Browse skills const skills = await client.skills.browse({ category: 'productivity', limit: 10 }); // Install skill const result = await client.skills.install({ skillId: 'skill-uuid-123', agentId: 'agent-uuid-456' }); // Rate skill await client.skills.rate({ skillId: 'skill-uuid-123', rating: 5, review: 'Excellent!' });
cURL Examples
# Browse skills curl -X GET "https://atom-saas.fly.dev/api/skills/marketplace?category=productivity&limit=10" \ -H "X-API-Key: sk-your-key" # Install skill curl -X POST "https://atom-saas.fly.dev/api/skills/install" \ -H "X-API-Key: sk-your-key" \ -H "Content-Type: application/json" \ -d '{ "skill_id": "skill-uuid-123", "agent_id": "agent-uuid-456" }' # Rate skill curl -X POST "https://atom-saas.fly.dev/api/skills/rate/skill-uuid-123" \ -H "X-API-Key: sk-your-key" \ -H "Content-Type: application/json" \ -d '{ "rating": 5, "review": "Excellent!" }'
Changelog
v1.0.0 (2026-04-05)
- Initial marketplace API documentation
- Skill, Agent, Domain, Canvas, Workflow marketplaces
- Public marketplace API
- Private marketplace endpoints
- Federation protocol
- Comprehensive error codes and troubleshooting
Support
For issues, questions, or feature requests:
- Documentation: https://docs.atomagentos.com
- GitHub Issues: https://github.com/rush86999/atom-saas/issues
- Email: support@atomagentos.com