ZeroPipeline API
CRM and sales pipeline management. Build deal pipelines, track customers, automate workflows, and get revenue analytics.
Base URL: https://pipeline.ainative.studio/api/v1
Interactive docs: https://pipeline.ainative.studio/api/v1/docs
Authentication
Authorization: Bearer YOUR_JWT_TOKEN
Or use an API key created via POST /api/v1/api-keys.
Health
| Method | Path | Description |
|---|---|---|
GET | /health/live | Liveness probe |
GET | /health/ready | Readiness probe — returns 503 if ZeroDB or Redis is unreachable |
GET | /api/v1/health | Readiness with dependency status |
GET | /api/v1/changelog | API version metadata |
Auth
Refresh token
POST /api/v1/auth/refresh
{ "refresh_token": "string" }
Response:
{ "access_token": "string", "refresh_token": "string" }
Revoke token
POST /api/v1/auth/revoke
{ "refresh_token": "string" }
Logout
POST /api/v1/auth/logout
Revokes the access token and all refresh tokens for the current user.
Password reset
POST /api/v1/auth/password-reset/request
{ "email": "user@example.com" }
Always returns 204 regardless of whether the email exists.
POST /api/v1/auth/password-reset/confirm
{ "token": "reset-token", "new_password": "newpass123" }
API Keys
Create API key
POST /api/v1/api-keys
{ "name": "My Integration" }
Response — plaintext key shown once only, store it immediately:
{
"id": "uuid",
"name": "My Integration",
"key": "zpk_live_xxxxxxxxxxxx",
"created_at": "2026-05-17T00:00:00Z"
}
List API keys
GET /api/v1/api-keys?include_revoked=false
Revoke API key
DELETE /api/v1/api-keys/{key_id}
Pipelines
Create pipeline
POST /api/v1/pipelines
{
"name": "Sales Pipeline",
"owner_id": "uuid",
"stages": [
{ "name": "Lead", "order_index": 0 },
{ "name": "Qualified", "order_index": 1 },
{ "name": "Closed Won", "order_index": 2 }
],
"meta": {}
}
List pipelines
GET /api/v1/pipelines?owner_id=uuid&limit=20&offset=0
Response:
{
"items": [...],
"limit": 20,
"offset": 0,
"total": 5
}
Get pipeline
GET /api/v1/pipelines/{pipeline_id}
Update pipeline
PATCH /api/v1/pipelines/{pipeline_id}
Supports optimistic locking via version.
{ "name": "New Name", "version": 3 }
Delete / restore pipeline
DELETE /api/v1/pipelines/{pipeline_id}
POST /api/v1/pipelines/{pipeline_id}/restore
Soft delete — restorable within 30 days.
Stages
Add stage
POST /api/v1/pipelines/{pipeline_id}/stages
{
"name": "Proposal",
"order_index": 2,
"rules": {
"required_fields": ["value", "expected_close_date"],
"disallow_skip": true,
"allowed_next_stage_ids": ["uuid"]
}
}
List stages
GET /api/v1/pipelines/{pipeline_id}/stages
Returns stages ordered by order_index.
Update stage
PATCH /api/v1/pipelines/{pipeline_id}/stages/{stage_id}
Reorder stages
POST /api/v1/pipelines/{pipeline_id}/stages/reorder
["uuid-stage-1", "uuid-stage-3", "uuid-stage-2"]
Delete stage
DELETE /api/v1/pipelines/{pipeline_id}/stages/{stage_id}
Deals
Deals are sales opportunities moving through pipeline stages.
Create deal
POST /api/v1/deals
{
"name": "Acme Corp - Enterprise",
"customer_id": "uuid",
"pipeline_id": "uuid",
"stage_id": "uuid",
"value": 25000.00,
"status": "open",
"expected_close_date": "2026-06-30",
"owner_id": "uuid"
}
Status values: open · won · lost
List deals
GET /api/v1/deals?pipeline_id=uuid&stage_id=uuid&status=open&q=acme&limit=20&offset=0
q requires at least 3 characters.
Get deal
GET /api/v1/deals/{deal_id}
Update deal
PATCH /api/v1/deals/{deal_id}
{ "stage_id": "uuid", "status": "won", "value": 30000.00 }
Deal health score
GET /api/v1/deals/{deal_id}/score
Returns an auto-calculated score from 0–100.
{ "score": 72 }
Add note to deal
POST /api/v1/deals/{deal_id}/notes
{ "text": "Called customer — moving forward with proposal." }
Creates an Activity record and returns it.
Create invoice from deal
POST /api/v1/deals/{deal_id}/invoice
Creates an invoice in the connected accounting system (QuickBooks or Xero). Deal must be in won status.
Errors:
400— deal is notwon409— invoice already exists422— no accounting integration connected
Response:
{ "invoice_id": "inv_xxx", "external_id": "QBO-12345" }
Delete / restore deal
DELETE /api/v1/deals/{deal_id}
POST /api/v1/deals/{deal_id}/restore
Customers
Create customer
POST /api/v1/customers
{
"name": "Jane Smith",
"email": "jane@acme.com",
"phone": "+1-555-0100",
"company": "Acme Corp",
"title": "VP Engineering",
"status": "active"
}
List customers
GET /api/v1/customers?page=1&page_size=20&status=active&q=acme
Check for duplicates
POST /api/v1/customers/check-duplicates?email=jane@acme.com&phone=+15550100
Check before creating to avoid duplicate records.
Import from CSV
POST /api/v1/customers/import
Content-Type: multipart/form-data
Response:
{
"total_imported": 95,
"total_skipped": 3,
"errors": ["Row 12: invalid email format"]
}
Get customer
GET /api/v1/customers/{customer_id}
Customer timeline
GET /api/v1/customers/{customer_id}/timeline
Returns the full activity history for the customer.
Update customer
PATCH /api/v1/customers/{customer_id}
Delete / restore customer
DELETE /api/v1/customers/{customer_id}
POST /api/v1/customers/{customer_id}/restore
Products
Products are items or services attachable to deals.
Create product
POST /api/v1/products
Returns 409 if SKU already exists. SKU is auto-uppercased.
{
"name": "Enterprise Plan",
"sku": "ENT-2026",
"description": "Full-featured enterprise subscription",
"price": 999.00,
"cost": 150.00,
"is_active": true
}
List products
GET /api/v1/products?is_active=true&limit=20&offset=0
Search products
GET /api/v1/products/search?query=enterprise&min_price=100&max_price=2000&is_active=true
Full-text search across name, SKU, and description.
Get product by ID
GET /api/v1/products/{product_id}
Get product by SKU
GET /api/v1/products/sku/{sku}
Update product
PATCH /api/v1/products/{product_id}
Supports optimistic locking via version.
{ "price": 1099.00, "version": 2 }
Delete product
DELETE /api/v1/products/{product_id}
Tasks
Tasks are to-dos linked to any entity (deal, customer, etc.).
Create task
POST /api/v1/tasks
{
"title": "Follow up on proposal",
"description": "Send revised pricing by EOD Friday",
"status": "pending",
"priority": "high",
"assignee_id": "uuid",
"due_date": "2026-05-23",
"related_to_type": "deal",
"related_to_id": "uuid"
}
Status values: pending · in_progress · completed · cancelled
Priority values: low · medium · high · urgent
List tasks
GET /api/v1/tasks?status=pending&assignee_id=uuid&priority=high&limit=20&offset=0
Get / update / delete task
GET /api/v1/tasks/{task_id}
PATCH /api/v1/tasks/{task_id}
DELETE /api/v1/tasks/{task_id}
POST /api/v1/tasks/{task_id}/restore
Activities
Activities are the immutable audit trail of events across all entities. They cannot be modified or deleted.
Log activity
POST /api/v1/activities
{
"activity_type": "deal.created",
"related_to_type": "deal",
"related_to_id": "uuid",
"description": "Deal created from inbound lead",
"meta": { "source": "web-form" }
}
List activities
GET /api/v1/activities?related_to_id=uuid&related_to_type=deal&activity_type=deal.created&from_date=2026-05-01&to_date=2026-05-31&limit=50&offset=0
Get activity types
GET /api/v1/activities/types
Returns all available activity type values with labels and categories.
Get activity feed for entity
GET /api/v1/activities/feed/{related_to_id}?limit=20&offset=0
Filter by type or actor
GET /api/v1/activities/by-type/{activity_type}
GET /api/v1/activities/by-actor/{actor_id}
Automations
Event-triggered workflows that fire actions automatically.
Create automation
POST /api/v1/automations
{
"name": "Send welcome email on deal won",
"trigger": {
"event": "deal.status_changed",
"conditions": { "status": "won" }
},
"actions": [
{
"type": "send_email",
"config": { "template_id": "welcome-won" }
}
],
"is_active": true
}
List automations
GET /api/v1/automations?limit=20&offset=0
Get / update / delete automation
GET /api/v1/automations/{automation_id}
PUT /api/v1/automations/{automation_id}
DELETE /api/v1/automations/{automation_id}
Manually trigger event
POST /api/v1/automations/trigger
{
"event": "deal.status_changed",
"payload": { "deal_id": "uuid", "status": "won" }
}
Analytics
Dashboard summary
GET /api/v1/analytics/dashboard
Top-level metrics: deal counts, revenue totals, task completion rates.
Revenue timeseries
GET /api/v1/analytics/revenue/timeseries?period=monthly&start=2026-01-01&end=2026-05-31&pipeline_id=uuid
Period values: weekly · monthly · quarterly
Deal analytics
GET /api/v1/analytics/deals?owner_id=uuid
Deal funnel: counts and values by stage and status.
Task analytics
GET /api/v1/analytics/tasks?assignee_id=uuid
Stale deals
GET /api/v1/analytics/stale-deals?days=14
Deals with no activity in the past N days. Max days = 365.
Pipeline analytics
GET /api/v1/analytics/pipeline/{pipeline_id}
Stage conversion rates, average deal age, velocity.
Customer analytics
GET /api/v1/analytics/customers
New customers over time, top customers by deal value.
Tags
GET /api/v1/tags?q=enter
List distinct tags across entities. q prefix-filters (min 1 char) — useful for autocomplete.
Billing
Create checkout session
POST /api/v1/payments/checkout
{ "plan_id": "pro_monthly" }
Response:
{ "session_id": "cs_xxx", "url": "https://checkout.stripe.com/..." }
Get subscription
GET /api/v1/payments/subscription
Response:
{
"status": "active",
"plan": "pro_monthly",
"current_period_start": "2026-05-01T00:00:00Z",
"current_period_end": "2026-06-01T00:00:00Z",
"cancel_at_period_end": false
}
Update subscription
POST /api/v1/payments/subscription
{ "plan_id": "enterprise_annual" }
Cancel subscription
POST /api/v1/payments/subscription/cancel
{ "reason": "switching tools" }
Billing portal
POST /api/v1/billing/portal-session
{ "return_url": "https://yourapp.com/settings" }
Response:
{ "url": "https://billing.stripe.com/session/..." }
Usage and history
GET /api/v1/payments/usage
GET /api/v1/payments/history?limit=20
GET /api/v1/me/billing-status
Usage response:
{
"current_usage": { "deals": 450, "pipelines": 3 },
"limits": { "deals": 1000, "pipelines": 10 },
"percentage": 45.0
}
Audit
Create / list / get audit logs
POST /api/v1/audit/logs
GET /api/v1/audit/logs?entity_type=deal&entity_id=uuid&action=stage_changed&page=1&page_size=50
GET /api/v1/audit/logs/{log_id}
GDPR export / delete
POST /api/v1/audit/gdpr/export
POST /api/v1/audit/gdpr/delete
{ "user_id": "uuid" }
Invitations
Invite user to org
POST /api/v1/orgs/{org_id}/invitations
Requires admin role. Sends email with a signed token link.
{ "email": "newuser@example.com", "role": "sales_rep" }
Role values: admin · sales_rep · viewer
List invitations
GET /api/v1/orgs/{org_id}/invitations?invitation_status=pending
Accept invitation
POST /api/v1/invitations/accept
Unauthenticated endpoint — secured by the signed token from email.
{ "token": "signed-token-from-email" }
Users
Get / update profile
GET /api/v1/users/me
PATCH /api/v1/users/me
{ "first_name": "Jane", "last_name": "Dev" }
Avatar
GET /api/v1/users/me/avatar
POST /api/v1/users/me/avatar ← multipart/form-data, JPEG/PNG, max 5 MB
DELETE /api/v1/users/me/avatar
Onboarding checklist
GET /api/v1/users/me/onboarding
Response:
{
"items": [
{ "key": "create_pipeline", "completed": true },
{ "key": "add_deal", "completed": false }
],
"completed_count": 1,
"total_count": 6
}
Account
Export account data (GDPR)
POST /api/v1/account/export
Returns 202 Accepted and emails a download link.
{ "email": "user@example.com" }
Download export
GET /api/v1/account/export/download?token=xxx
Unauthenticated — secured by token.
Delete account
DELETE /api/v1/account
Returns 202 Accepted. Soft-deletes immediately; hard-delete after grace period.
Response:
{
"soft_deleted_at": "2026-05-17T00:00:00Z",
"hard_delete_scheduled_at": "2026-06-17T00:00:00Z"
}
Error Responses
{
"error": "not_found",
"detail": "Pipeline not found",
"code": "PIPELINE_404"
}
| Status | Meaning |
|---|---|
400 | Bad request / validation error |
401 | Missing or invalid token |
403 | Insufficient role |
404 | Resource not found |
409 | Conflict (duplicate SKU, invoice already exists) |
422 | Unprocessable (missing integration, etc.) |
503 | ZeroDB or Redis unavailable |