Deals API
Deals API
Deals represent sales opportunities in your pipeline. Each deal has a stage, value, and can be associated with an organization, contact, and assigned to a team member.
Endpoints Overview
| Method | Endpoint | Description |
|---|---|---|
| GET | /api-v1-deals | List all deals with filtering, sorting, and pagination |
| GET | /api-v1-deals/:id | Get a single deal with related data |
| POST | /api-v1-deals | Create a new deal |
| PATCH | /api-v1-deals/:id | Update an existing deal |
| PATCH | /api-v1-deals/:id/stage | Update deal stage only (optimized endpoint) |
| DELETE | /api-v1-deals/:id | Soft delete a deal |
Required Scopes
- Read operations:
read:deals - Write operations:
write:deals
List Deals
List all deals with support for filtering, sorting, pagination, and expanding related data.
Endpoint: GET /api-v1-deals
Scope: read:deals
Query Parameters
Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Number of records per page (max: 100) |
page | integer | 1 | Page number for offset-based pagination |
per_page | integer | 50 | Alternative to limit for offset-based pagination |
cursor | string | - | Cursor for cursor-based pagination |
Filtering
Filters can be applied using the following syntax:
- Simple equality:
?stage_id=uuid - With operator:
?value[gte]=1000or?title[like]=Enterprise
Supported operators: eq, ne, gt, gte, lt, lte, like, in
Filterable fields:
title- Deal title (string)stage_id- Deal stage UUIDorganization_id- Associated organization UUIDcontact_id- Associated contact UUIDassigned_to- Assigned user UUIDcreated_at- Creation timestamp (ISO 8601)expected_close_date- Expected close date (ISO 8601)
Sorting
Use the sort parameter with field name. Prefix with - for descending order.
Examples:
?sort=title- Sort by title ascending?sort=-value- Sort by value descending
Sortable fields: title, value, created_at, updated_at, expected_close_date
Including Related Data
Use the include parameter to expand related resources in the response:
?include=organization,contact,stage,assigned_userAvailable includes:
organization- Include organization detailscontact- Include contact detailsstage- Include deal stage detailsassigned_user- Include assigned user details
Response
Returns a paginated list of deals.
Without includes:
{ "data": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-1", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z" } ], "pagination": { "total": 150, "limit": 50, "page": 1, "per_page": 50, "total_pages": 3, "has_more": true }}With includes:
{ "data": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-1", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "organization": { "id": "org-uuid-1", "name": "Acme Retail Shop", "status": "active" }, "contact": { "id": "contact-uuid-1", "first_name": "John", "last_name": "Doe" }, "stage": { "id": "stage-uuid-1", "name": "Qualified", "color": "#3b82f6", "position": 2 }, "assigned_user": { "id": "user-uuid-1", "full_name": "Sarah Smith", "email": "sarah@company.com" } } ], "pagination": { "total": 150, "limit": 50, "page": 1, "per_page": 50, "total_pages": 3, "has_more": true }}Example Request
curl -X GET "https://your-project.supabase.co/functions/v1/api-v1-deals?limit=20&include=organization,stage&value[gte]=10000&sort=-value" \ -H "Authorization: Bearer YOUR_API_KEY"Get Single Deal
Retrieve a single deal by its unique ID with all related data.
Endpoint: GET /api-v1-deals/:id
Scope: read:deals
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID | Yes | Deal ID |
Response
Returns a single deal with all related data (organization, contact, stage, assigned user).
{ "data": { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-1", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "organization": { "id": "org-uuid-1", "name": "Acme Retail Shop", "status": "active" }, "contact": { "id": "contact-uuid-1", "first_name": "John", "last_name": "Doe" }, "stage": { "id": "stage-uuid-1", "name": "Qualified", "color": "#3b82f6", "position": 2 }, "assigned_user": { "id": "user-uuid-1", "full_name": "Sarah Smith", "email": "sarah@company.com" } }}Example Request
curl -X GET "https://your-project.supabase.co/functions/v1/api-v1-deals/123e4567-e89b-12d3-a456-426614174000" \ -H "Authorization: Bearer YOUR_API_KEY"Error Responses
404 Not Found:
{ "error": { "code": "NOT_FOUND", "message": "Deal not found" }}Create Deal
Create a new deal in your pipeline.
Endpoint: POST /api-v1-deals
Scope: write:deals
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Deal title (trimmed, non-empty) |
value | number | No | Deal value (default: 0) |
currency | string | No | Currency code (default: “EUR”) |
stage_id | UUID | No | Deal stage (defaults to first stage if not provided) |
organization_id | UUID | No | Associated organization (must exist in your company) |
contact_id | UUID | No | Associated contact (must exist in your company) |
assigned_to | UUID | No | User assigned to this deal |
expected_close_date | string | No | Expected close date (ISO 8601 format: YYYY-MM-DD) |
probability | number | No | Win probability percentage (0-100) |
metadata | object | No | Custom metadata as JSON object |
Response
Returns the created deal with all related data and a 201 Created status.
{ "data": { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-1", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "organization": { "id": "org-uuid-1", "name": "Acme Retail Shop", "status": "active" }, "contact": { "id": "contact-uuid-1", "first_name": "John", "last_name": "Doe" }, "stage": { "id": "stage-uuid-1", "name": "Qualified", "color": "#3b82f6", "position": 2 }, "assigned_user": { "id": "user-uuid-1", "full_name": "Sarah Smith", "email": "sarah@company.com" } }}Example Request
curl -X POST "https://your-project.supabase.co/functions/v1/api-v1-deals" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-1", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75 }'Error Responses
400 Validation Error (missing title):
{ "error": { "code": "VALIDATION_ERROR", "message": "Title is required", "details": [ { "field": "title", "message": "Title is required" } ] }}400 Validation Error (invalid stage):
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid stage", "details": [ { "field": "stage_id", "message": "Stage not found or does not belong to your company" } ] }}400 Validation Error (invalid organization):
{ "error": { "code": "VALIDATION_ERROR", "message": "Organization not found", "details": [ { "field": "organization_id", "message": "Organization not found" } ] }}Update Deal
Update an existing deal. Only provided fields will be updated.
Endpoint: PATCH /api-v1-deals/:id
Scope: write:deals
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID | Yes | Deal ID |
Request Body
All fields are optional. Only include fields you want to update.
| Field | Type | Description |
|---|---|---|
title | string | Deal title |
value | number | Deal value |
currency | string | Currency code |
stage_id | UUID | Deal stage (must belong to your company) |
organization_id | UUID or null | Associated organization (set to null to remove) |
contact_id | UUID or null | Associated contact (set to null to remove) |
assigned_to | UUID or null | Assigned user (set to null to unassign) |
expected_close_date | string or null | Expected close date (ISO 8601 or null) |
probability | number | Win probability percentage (0-100) |
metadata | object | Custom metadata (replaces existing) |
Response
Returns the updated deal with all related data.
{ "data": { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order - Updated", "value": 30000, "currency": "EUR", "stage_id": "stage-uuid-2", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-04-15", "probability": 85, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-16T14:20:00Z", "organization": { "id": "org-uuid-1", "name": "Acme Retail Shop", "status": "active" }, "contact": { "id": "contact-uuid-1", "first_name": "John", "last_name": "Doe" }, "stage": { "id": "stage-uuid-2", "name": "Sample Sent", "color": "#8b5cf6", "position": 3 }, "assigned_user": { "id": "user-uuid-1", "full_name": "Sarah Smith", "email": "sarah@company.com" } }}Example Request
curl -X PATCH "https://your-project.supabase.co/functions/v1/api-v1-deals/123e4567-e89b-12d3-a456-426614174000" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Q1 Bulk Order - Updated", "value": 30000, "stage_id": "stage-uuid-2", "probability": 85 }'Error Responses
404 Not Found:
{ "error": { "code": "NOT_FOUND", "message": "Deal not found" }}400 No Fields:
{ "error": { "code": "INVALID_REQUEST", "message": "No fields to update" }}Update Deal Stage
Optimized endpoint for updating only the deal stage. This is commonly used for drag-and-drop pipeline interfaces.
Endpoint: PATCH /api-v1-deals/:id/stage
Scope: write:deals
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID | Yes | Deal ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
stage_id | UUID | Yes | New deal stage UUID (must belong to your company) |
Response
Returns the updated deal with all related data.
{ "data": { "id": "123e4567-e89b-12d3-a456-426614174000", "title": "Q1 Bulk Order", "value": 25000, "currency": "EUR", "stage_id": "stage-uuid-3", "organization_id": "org-uuid-1", "contact_id": "contact-uuid-1", "assigned_to": "user-uuid-1", "expected_close_date": "2024-03-31", "probability": 75, "metadata": {}, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-16T14:25:00Z", "organization": { "id": "org-uuid-1", "name": "Acme Retail Shop", "status": "active" }, "contact": { "id": "contact-uuid-1", "first_name": "John", "last_name": "Doe" }, "stage": { "id": "stage-uuid-3", "name": "First Order", "color": "#10b981", "position": 4 }, "assigned_user": { "id": "user-uuid-1", "full_name": "Sarah Smith", "email": "sarah@company.com" } }}Example Request
curl -X PATCH "https://your-project.supabase.co/functions/v1/api-v1-deals/123e4567-e89b-12d3-a456-426614174000/stage" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "stage_id": "stage-uuid-3" }'Error Responses
400 Validation Error (missing stage_id):
{ "error": { "code": "INVALID_REQUEST", "message": "stage_id is required" }}400 Validation Error (invalid stage):
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid stage", "details": [ { "field": "stage_id", "message": "Stage not found" } ] }}Delete Deal
Soft delete a deal. The deal is not permanently deleted but marked with a deleted_at timestamp and will no longer appear in API responses.
Endpoint: DELETE /api-v1-deals/:id
Scope: write:deals
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | UUID | Yes | Deal ID |
Response
Returns a deletion confirmation.
{ "data": { "deleted": true }}Example Request
curl -X DELETE "https://your-project.supabase.co/functions/v1/api-v1-deals/123e4567-e89b-12d3-a456-426614174000" \ -H "Authorization: Bearer YOUR_API_KEY"Error Responses
404 Not Found:
{ "error": { "code": "NOT_FOUND", "message": "Deal not found" }}Deal Stages
Deal stages represent the pipeline stages in your sales process. Each company has its own set of deal stages with custom names, colors, and positions.
Common default stages include:
- Lead - Initial contact or inquiry
- Qualified - Qualified opportunity
- Sample Sent - Product sample sent
- First Order - First order placed
- Active Customer - Ongoing customer relationship
- At Risk - Customer relationship at risk
- Lost - Lost opportunity
Stages are ordered by the position field and can be customized per company.
Deal Fields Explained
value & currency
The monetary value of the deal. value is a number and currency is a 3-letter currency code (e.g., “EUR”, “USD”, “GBP”). Used for revenue forecasting and reporting.
probability
Win probability percentage (0-100). Represents the likelihood of closing this deal. Can be used for weighted pipeline forecasting.
expected_close_date
The expected date when the deal will close (ISO 8601 date format: YYYY-MM-DD). Used for pipeline forecasting and follow-up reminders.
metadata
Custom JSON object for storing additional data specific to your use case. The API does not validate the structure of this field.
Multi-Tenant Isolation
All deals are automatically scoped to your company. You can only access deals that belong to your company (determined by your API key’s company_id).
When creating or updating a deal:
stage_idmust belong to your companyorganization_id(if provided) must belong to your companycontact_id(if provided) must belong to your company
Related Resources
- Organizations: Deals can be associated with an organization. See Organizations API
- Contacts: Deals can be associated with a contact. See Contacts API
- Deal Stages: Manage custom pipeline stages (documentation coming soon)