Integrator API
The Integrator API enables B2B partners to resell Snipara to their clients with isolated workspaces, dedicated API keys, and configurable resource limits.
Partner Program Only
The Integrator API is available to approved partners. Apply to the Partner Program to get started.
Overview
The Integrator system has a hierarchical structure:
Integrator (B2B Partner)
└── Workspace (white-label container)
├── Client A (end-user)
│ ├── Project (isolated Snipara project)
│ └── API Keys (snipara_ic_*)
├── Client B
│ ├── Project
│ └── API Keys
└── Webhooks (client lifecycle events)Authentication
All Integrator API endpoints require your standard Snipara API key with integrator permissions. You must be logged in as an approved integrator.
curl -H "Authorization: Bearer YOUR_SESSION_TOKEN" https://www.snipara.com/api/integrator/...For MCP Server access (api.snipara.com), use your team API key with the X-API-Key header.
Base URLs
| Service | Base URL | Use Case |
|---|---|---|
| Web App | https://www.snipara.com/api/integrator | Dashboard operations (requires session) |
| MCP Server | https://api.snipara.com/v1/integrator | Programmatic access (requires API key) |
Integrator Tiers
| Tier | Price | Client Limit |
|---|---|---|
| STARTER | $99/mo | 10 clients |
| GROWTH | $249/mo | 50 clients |
| SCALE | $499/mo | 200 clients |
| ENTERPRISE | Custom | Unlimited |
Client Bundles
Each client is assigned a bundle that determines their resource limits:
| Bundle | Price | Queries/mo | Memories | Swarms | Agents/Swarm | Documents | Storage |
|---|---|---|---|---|---|---|---|
LITE | $19/mo | 500 | 100 | 1 | 5 | 50 | 100 MB |
STANDARD | $49/mo | 5,000 | 500 | 5 | 10 | 200 | 1 GB |
UNLIMITED | $99/mo | Unlimited | Unlimited | Unlimited | 20 | Unlimited | 10 GB |
Workspace API
Get Workspace
GET /api/integrator/workspaceReturns your workspace details, including client count and limits.
Response
{ "success": true, "data": { "id": "ws_abc123", "name": "Acme Workspace", "slug": "acme", "webhookUrl": "https://acme.com/webhooks/snipara", "hasWebhookSecret": true, "clientCount": 5, "clientLimit": 10, "tier": "STARTER" }}Create Workspace
POST /api/integrator/workspace{ "name": "Acme Workspace", "slug": "acme" // lowercase, alphanumeric + hyphens only}Update Workspace
PATCH /api/integrator/workspace{ "name": "New Name", // optional "webhookUrl": "https://...", // optional "webhookSecret": "your-secret" // optional}Clients API
List Clients
GET /api/integrator/clients?limit=50&offset=0&is_active=true&bundle=STANDARDQuery Parameters
limit- Results per page (default: 50, max: 100)offset- Pagination offsetis_active- Filter by status:trueorfalsebundle- Filter by bundle:LITE,STANDARD,UNLIMITED
Response
{ "success": true, "data": { "clients": [ { "id": "client_456", "projectId": "proj_789", "projectSlug": "acme-client-a", "name": "Client A", "email": "admin@clienta.com", "externalId": "cust_123", "bundle": "STANDARD", "isActive": true, "limits": { "queries_per_month": 2000, ... } } ], "pagination": { "total": 5, "limit": 50, "offset": 0, "hasMore": false } }}Create Client
POST /api/integrator/clients{ "name": "Client A", "email": "admin@clienta.com", "external_id": "cust_123", // optional, your internal ID "bundle": "STANDARD" // LITE, STANDARD, or UNLIMITED}Creating a client automatically provisions an isolated Snipara project with the slug format: {workspace_slug}-{client_name}.
Get Client
GET /api/integrator/clients/:clientIdUpdate Client
PATCH /api/integrator/clients/:clientId{ "name": "New Name", // optional "email": "new@email.com", // optional "bundle": "UNLIMITED", // optional "is_active": false // optional, deactivate client}Delete Client
DELETE /api/integrator/clients/:clientIdWarning: Permanent Deletion
Deleting a client permanently removes their project and all associated data. This action cannot be undone.
Client API Keys
Client API keys use the snipara_ic_ prefix to distinguish them from regular API keys. These keys grant access only to the client's project.
List API Keys
GET /api/integrator/clients/:clientId/api-keysCreate API Key
POST /api/integrator/clients/:clientId/api-keys{ "name": "Production Key", "expires_in_days": 365 // optional, null for no expiration}Response
{ "success": true, "data": { "id": "key_abc123", "name": "Production Key", "key": "snipara_ic_a1b2c3d4...", // ONLY shown once! "keyPrefix": "snipara_ic_a1b2", "expiresAt": "2027-02-19T00:00:00Z" }}Save the API Key
The full API key is only returned once during creation. Store it securely and provide it to your client.
Revoke API Key
DELETE /api/integrator/clients/:clientId/api-keys/:keyIdWebhooks
Configure a webhook URL in your workspace to receive real-time notifications about client lifecycle events.
Events
| Event | Trigger |
|---|---|
client.created | New client added to workspace |
client.updated | Client details changed (name, email, bundle, status) |
client.deleted | Client removed from workspace |
api_key.created | New API key generated for a client |
api_key.revoked | API key revoked |
| Swarm & Task Events | |
task.created | New task created in swarm |
task.claimed | Agent claimed a task |
task.completed | Agent completed a task successfully |
task.failed | Task execution failed |
task.blocked | Task blocked by dependency or issue |
task.timeout | Task exceeded deadline — emitted automatically by the platform watchdog (see below) |
htask.completed | Hierarchical task (N3) completed with evidence |
htask.blocked | Hierarchical task blocked with propagation |
htask.closure_ready | Parent task ready to close (all children done) |
Payload Format
{ "event": "client.created", "timestamp": "2026-02-19T15:30:00Z", "workspace_id": "ws_abc123", "data": { "client_id": "client_456", "name": "Client A", "email": "admin@clienta.com", "bundle": "STANDARD", "project_id": "proj_789", "project_slug": "acme-client-a" }}Task Event Payload
{ "event_id": "evt_abc123", "event_type": "task.completed", "workspace_id": "ws_abc123", "created_at": "2026-03-27T14:30:00Z", "data": { "task_id": "task_xyz789", "swarm_id": "swarm_456", "agent_id": "mike", "status": "COMPLETED", "result": { "output": "..." } }}Task Watchdog — Automatic Timeout Detection
Snipara runs a platform-level watchdog that automatically monitors all swarm tasks and hierarchical tasks across every integrator workspace. You do not need to configure anything — timeouts are emitted as task.timeout webhooks to your endpoint.
| Scenario | Trigger | reason field |
|---|---|---|
| Task claimed but never completed | claimedAt older than swarm taskTimeout (default 5 min) | execution_timeout |
| Task assigned but agent never claimed it | createdAt older than swarm claimTimeout (default 10 min) | never_claimed |
| Task created with no agent assigned | createdAt older than swarm claimTimeout | unclaimed |
| Hierarchical task stalled | No updatedAt change for 24 hours while IN_PROGRESS | htask_stalled |
Timeouts are per-swarm. Configure them via rlm_swarm_update with taskTimeout and claimTimeout (in seconds). The watchdog scans every 2 minutes.
Task Timeout Payload
{ "event_id": "evt_abc123", "event_type": "task.timeout", "workspace_id": "ws_abc123", "created_at": "2026-03-27T17:00:00Z", "data": { "task_id": "task_xyz789", "swarm_id": "swarm_456", "agent_id": "mike", "reason": "execution_timeout", "stalled_for_seconds": 720 }}Use the reason field to differentiate scenarios in your handler — for example, re-dispatch on execution_timeout, alert on never_claimed, or escalate on htask_stalled.
Signature Verification
If you configure a webhook secret, all deliveries include an X-Snipara-Signature header for verification:
X-Snipara-Signature: sha256=abc123...Verify using HMAC-SHA256:
import crypto from "crypto";function verifyWebhook(payload: string, signature: string, secret: string): boolean { const expected = "sha256=" + crypto.createHmac("sha256", secret).update(payload).digest("hex"); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));}Webhook Event Log
Inspect delivery history and retry failed events via the event log endpoints.
List Delivery Events
GET /v1/integrator/webhook-events| Parameter | Type | Description |
|---|---|---|
limit | integer | Number of results to return (default 20) |
offset | integer | Pagination offset |
status | string | Filter by delivery status: pending, delivered, failed |
event_type | string | Filter by event type (e.g. task.completed) |
Retry a Failed Delivery
POST /v1/integrator/webhook-events/:eventId/retryRe-queues the specified event for delivery. Returns the updated event record with the new delivery attempt.
Send a Test Event
POST /v1/integrator/webhook-testSends a test.ping event to your configured webhook URL. Useful for verifying endpoint reachability and signature verification without waiting for a real event.
Bundle Limit Enforcement
When a client exceeds their bundle limits, the MCP API returns a 429 error:
{ "success": false, "error": { "code": "BUNDLE_LIMIT_EXCEEDED", "message": "Monthly query limit exceeded", "limit": 500, "current": 201, "reset_at": "2026-03-01T00:00:00Z" }}Enforced Limits
| Limit | Enforcement Point |
|---|---|
| Queries/month | Every MCP tool call |
| Memories | rlm_remember tool |
| Swarms | rlm_swarm_create tool |
| Agents/swarm | rlm_swarm_join tool |
| Documents | Document upload endpoints |
| Storage | File upload size validation |
Client API Key Usage
Once you provide a client with their snipara_ic_* API key, they can use it with any MCP-compatible client.
Claude Code Configuration
// .mcp.json{ "mcpServers": { "snipara": { "type": "http", "url": "https://api.snipara.com/mcp/{project_slug}", "headers": { "X-API-Key": "snipara_ic_..." } } }}The project_slug is automatically set when you create the client (format: {workspace_slug}-{client_name}).
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid request body or parameters |
| 401 | UNAUTHORIZED | Missing or invalid authentication |
| 403 | FORBIDDEN | Not an approved integrator |
| 404 | NOT_FOUND | Workspace, client, or key not found |
| 409 | CONFLICT | Duplicate email, external_id, or slug |
| 429 | CLIENT_LIMIT_EXCEEDED | Tier client limit reached |
| 500 | INTERNAL_ERROR | Server error |