Appearance
Products & Services API
The Products & Services API allows you to manage your product catalog and service offerings. This is essential for communication integrations that need to reference available products/services when creating quotes, invoices, or sending communications to clients.
Base Endpoint
/v1/productsAuthentication
All requests require the products:read scope for GET operations and products:write scope for POST/PUT operations.
List Products/Services
Retrieve a paginated list of products and services.
Endpoint
GET /v1/productsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
type | string | Filter by type: product or service |
limit | integer | Number of results per page (default: 50, max: 100) |
offset | integer | Number of results to skip (default: 0) |
order_by | string | Field to sort by: created_at, updated_at, name, price (default: created_at) |
order | string | Sort order: asc or desc (default: desc) |
Example Request
bash
curl -X GET \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products?type=service&limit=20' \
-H 'Authorization: Bearer YOUR_API_KEY'Example Response
json
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "service",
"name": "Website Design",
"description": "Custom website design and development",
"pricing_model": "fixed",
"price": 2500.00,
"sku": null,
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"created_by": "789e0123-e45b-67c8-d901-234567890abc"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"type": "product",
"name": "Premium Widget",
"description": "High-quality widget with lifetime warranty",
"pricing_model": "fixed",
"price": 99.99,
"sku": "WIDGET-PREM-001",
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"created_at": "2024-01-14T09:15:00Z",
"updated_at": "2024-01-14T09:15:00Z",
"created_by": "789e0123-e45b-67c8-d901-234567890abc"
}
],
"count": 2,
"has_more": false
}Get Product/Service
Retrieve a specific product or service by ID.
Endpoint
GET /v1/products/:idPath Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Product/service ID |
Example Request
bash
curl -X GET \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer YOUR_API_KEY'Example Response
json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "service",
"name": "Website Design",
"description": "Custom website design and development",
"pricing_model": "fixed",
"price": 2500.00,
"sku": null,
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"created_by": "789e0123-e45b-67c8-d901-234567890abc"
}
}Create Product/Service
Create a new product or service.
Endpoint
POST /v1/productsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Either product or service |
name | string | Yes | Product/service name (max 255 characters) |
description | string | No | Detailed description |
pricing_model | string | Yes | Either fixed or hourly |
price | number | Yes | Unit price (must be >= 0) |
sku | string | No | Stock keeping unit (for products) |
Example Request
bash
curl -X POST \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: unique-key-123' \
-d '{
"type": "service",
"name": "Consulting Services",
"description": "Expert consulting and advisory services",
"pricing_model": "hourly",
"price": 150.00
}'Example Response
json
{
"data": {
"id": "770e8400-e29b-41d4-a716-446655440002",
"type": "service",
"name": "Consulting Services",
"description": "Expert consulting and advisory services",
"pricing_model": "hourly",
"price": 150.00,
"sku": null,
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"created_at": "2024-01-16T14:20:00Z",
"updated_at": "2024-01-16T14:20:00Z",
"created_by": "789e0123-e45b-67c8-d901-234567890abc"
}
}Update Product/Service
Update an existing product or service.
Endpoint
PUT /v1/products/:idPath Parameters
| Parameter | Type | Description |
|---|---|---|
id | uuid | Product/service ID |
Request Body
All fields are optional. Only include fields you want to update.
| Field | Type | Description |
|---|---|---|
type | string | Either product or service |
name | string | Product/service name (max 255 characters) |
description | string | Detailed description |
pricing_model | string | Either fixed or hourly |
price | number | Unit price (must be >= 0) |
sku | string | Stock keeping unit (for products) |
Example Request
bash
curl -X PUT \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"price": 2750.00,
"description": "Updated: Custom website design and development with responsive design"
}'Example Response
json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "service",
"name": "Website Design",
"description": "Updated: Custom website design and development with responsive design",
"pricing_model": "fixed",
"price": 2750.00,
"sku": null,
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-16T15:45:00Z",
"created_by": "789e0123-e45b-67c8-d901-234567890abc"
}
}Data Model
Product/Service Object
| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier |
type | string | Either product or service |
name | string | Product/service name |
description | string | null | Detailed description |
pricing_model | string | Either fixed or hourly |
price | number | Unit price |
sku | string | null | Stock keeping unit (typically for products) |
tenant_id | uuid | Tenant identifier (automatically set) |
created_at | timestamp | Creation timestamp |
updated_at | timestamp | Last update timestamp |
created_by | uuid | User who created the product/service |
Use Cases for Communication Integrations
1. Populate Product Dropdowns
When creating quotes or invoices through integrations, query available products/services to populate selection lists:
bash
# Get all services for a dropdown
curl -X GET \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products?type=service' \
-H 'Authorization: Bearer YOUR_API_KEY'2. Validate Product References
Before creating invoice/quote line items, verify that referenced products exist:
bash
# Check if product exists
curl -X GET \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products/PRODUCT_ID' \
-H 'Authorization: Bearer YOUR_API_KEY'3. Display Product Information
Include product details in communications sent to clients:
bash
# Get product details for email template
curl -X GET \
'https://your-instance.supabase.co/functions/v1/crm-api/v1/products/PRODUCT_ID' \
-H 'Authorization: Bearer YOUR_API_KEY'Error Responses
404 Not Found
json
{
"error": {
"message": "Product not found",
"code": "NOT_FOUND"
}
}400 Bad Request
json
{
"error": {
"message": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"field": "price",
"issue": "Price must be a positive number"
}
}
}403 Forbidden
json
{
"error": {
"message": "Missing required scope: products:read",
"code": "INSUFFICIENT_SCOPE",
"required": "products:read",
"granted": ["clients:read"]
}
}409 Conflict
json
{
"error": {
"message": "Product with this SKU already exists",
"code": "DUPLICATE"
}
}Notes
- All products/services are tenant-scoped automatically
- SKU values should be unique within a tenant
- Products with
pricing_model: "hourly"are typically used with timesheets - Products with
pricing_model: "fixed"have a one-time price per unit - The
typefield distinguishes between physical products (with inventory) and services (no inventory)

