API Reference
Modality REST API
The Modality API follows REST conventions. All endpoints are versioned under /api/v1/ and return JSON responses. Authenticate with session cookies (browser) or API keys (server-to-server).
Authentication
Modality uses Auth.js (NextAuth v5) with JWT session strategy. Browser clients authenticate via the standard OAuth flow and include session cookies automatically. For API access from external services, use the workspace API key.
API Key Authentication
curl -H "Authorization: Bearer YOUR_API_KEY" \ https://modalitystudio.com/api/v1/contacts
Response Format
// Success (single item)
{ "data": { "id": "...", ... } }
// Success (list)
{ "data": [...], "total": 42 }
// Error
{ "error": "Description of the error" }Contacts
Manage CRM contacts with tags, lists, custom fields, and activity tracking.
/api/v1/contactsAuth RequiredList all contacts in the workspace. Supports pagination, sorting, and filtering.
Query Parameters
workspaceIdstringrequiredWorkspace IDpageSizenumberItems per page (default: 50)pagenumberPage number (default: 1)sortBystringSort field (default: createdAt)sortDirectionasc|descSort direction (default: desc)searchstringSearch by name or emailtagstringFilter by tag sluglistIdstringFilter by list IDResponse
{
"data": [
{
"id": "clx...",
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"phone": null,
"source": "form",
"status": "ACTIVE",
"tags": [{ "id": "...", "name": "VIP", "slug": "vip" }],
"createdAt": "2026-01-15T10:30:00Z"
}
],
"total": 1842
}/api/v1/contactsAuth RequiredCreate a new contact or upsert by email.
Request Body (JSON)
emailstringrequiredContact email addressfirstNamestringFirst namelastNamestringLast namephonestringPhone numbersourcestringLead source identifiertagIdsstring[]Array of tag IDs to attachResponse
{ "data": { "id": "clx...", "email": "user@example.com", ... } }/api/v1/contacts/:idAuth RequiredGet a single contact with full details including tags, lists, and custom field values.
Response
{
"data": {
"id": "clx...",
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"tags": [...],
"lists": [...],
"customFields": { "company": "Acme Inc" },
"createdAt": "2026-01-15T10:30:00Z"
}
}/api/v1/contacts/:idAuth RequiredUpdate a contact's fields. Supports adding/removing tags.
Request Body (JSON)
firstNamestringUpdated first namelastNamestringUpdated last namephonestringUpdated phoneaddTagIdstringTag ID to addremoveTagIdstringTag ID to remove/api/v1/contacts/importAuth RequiredBulk import contacts from CSV data.
Request Body (JSON)
contactsobject[]requiredArray of contact objects with mapped fieldstagIdsstring[]Tags to apply to all imported contactsResponse
{ "data": { "imported": 150, "updated": 23, "errors": 2 } }Events
Create and manage events with ticket types.
/api/v1/eventsAuth RequiredList all events in the workspace.
Query Parameters
workspaceIdstringrequiredWorkspace IDstatusstringFilter by status: DRAFT, PUBLISHED, CANCELLEDResponse
{
"data": [
{
"id": "clx...",
"title": "Summer Festival",
"slug": "summer-festival",
"status": "PUBLISHED",
"startsAt": "2026-07-15T18:00:00Z",
"endsAt": "2026-07-15T23:00:00Z",
"venue": "Outdoor Arena",
"ticketTypes": [
{ "id": "...", "name": "GA", "price": 4500, "capacity": 2000 }
]
}
],
"total": 5
}/api/v1/eventsAuth RequiredCreate a new event.
Request Body (JSON)
titlestringrequiredEvent titledescriptionstringEvent description (supports markdown)startsAtISO 8601requiredEvent start date/timeendsAtISO 8601Event end date/timevenuestringVenue nameaddressstringVenue addressstatusstringDRAFT or PUBLISHED (default: DRAFT)/api/v1/events/:id/ticket-typesAuth RequiredAdd a ticket type to an event.
Request Body (JSON)
namestringrequiredTicket type name (e.g., GA, VIP)pricenumberrequiredPrice in cents (e.g., 4500 = $45.00)capacitynumberMaximum tickets availabledescriptionstringTicket type description/api/v1/events/:id/checkoutCreate a Stripe checkout session for ticket purchase. Public endpoint — no auth required.
Request Body (JSON)
emailstringrequiredBuyer emailfirstNamestringBuyer first namelastNamestringBuyer last nameitemsarrayrequired[ { ticketTypeId, quantity } ]Response
{
"data": {
"checkoutUrl": "https://checkout.stripe.com/...",
"orderId": "clx..."
}
}Forms
Manage forms and their submissions.
/api/v1/formsAuth RequiredList all forms in the workspace.
Query Parameters
workspaceIdstringrequiredWorkspace ID/api/v1/formsAuth RequiredCreate a new form.
Request Body (JSON)
namestringrequiredForm namefieldsFormField[]Array of field definitionssettingsobjectForm settings (theme, payment, notifications)statusstringDRAFT or PUBLISHED/api/v1/submissions/:slugSubmit a form. Public endpoint. Creates/upserts contact and stores submission data.
Request Body (JSON)
(dynamic)objectrequiredForm field values keyed by field IDResponse
{
"data": {
"id": "clx...",
"formId": "clx...",
"contactId": "clx...",
"paymentUrl": "https://..." // if payment form
}
}Campaigns
Create and manage email campaigns.
/api/v1/campaignsAuth RequiredList all campaigns in the workspace.
Query Parameters
workspaceIdstringrequiredWorkspace ID/api/v1/campaignsAuth RequiredCreate a new campaign.
Request Body (JSON)
namestringrequiredCampaign namesubjectstringrequiredEmail subject linehtmlContentstringHTML email contenttextContentstringPlain text fallbackaudienceTypestringALL, TAG, or LISTaudienceValuestringTag slug or list ID for targetingconnectorIdstringIntegration connector ID for delivery/api/v1/campaigns/:id/sendAuth RequiredSend or schedule a campaign for delivery.
Request Body (JSON)
scheduledForISO 8601Schedule send time (omit for immediate)Automations
Manage workflow automations.
/api/v1/automationsAuth RequiredList all automations in the workspace.
Query Parameters
workspaceIdstringrequiredWorkspace ID/api/v1/automationsAuth RequiredCreate a new automation.
Request Body (JSON)
namestringrequiredAutomation nametriggerobjectrequired{ type, config } — trigger definitionactionsobject[]requiredArray of { type, config } action stepsstatusstringACTIVE or PAUSED (default: ACTIVE)Custom Objects
Create and manage custom data structures.
/api/v1/objectsAuth RequiredList all object types in the workspace.
Response
{
"data": [
{
"id": "clx...",
"name": "Deals",
"slug": "deals",
"singularName": "Deal",
"icon": "Briefcase",
"attributes": [
{ "name": "Stage", "type": "select", "options": [...] },
{ "name": "Value", "type": "currency" }
]
}
]
}/api/v1/objectsAuth RequiredCreate a new object type.
Request Body (JSON)
namestringrequiredPlural name (e.g., Deals)slugstringrequiredURL-safe identifiersingularNamestringSingular form (e.g., Deal)iconstringLucide icon name/api/v1/objects/:slug/recordsAuth RequiredList records in an object type with sorting and filtering.
Query Parameters
pagenumberPage numberpageSizenumberItems per pagesortBystringAttribute to sort bysortDirasc|descSort directionsearchstringFull-text search across attributes/api/v1/objects/:slug/recordsAuth RequiredCreate a new record.
Request Body (JSON)
titlestringrequiredRecord titleattributesobjectKey-value pairs for custom attributesWebhooks
Receive real-time notifications when events occur in your workspace.
Stripe Webhook
Configure Stripe webhooks to point to /api/v1/webhooks/stripe. Modality handles the following events:
checkout.session.completed— fulfills ticket orders, creates tickets, sends confirmation emailcustomer.subscription.created— activates workspace subscriptioncustomer.subscription.updated— handles plan changescustomer.subscription.deleted— handles cancellationsinvoice.payment_succeeded— records successful paymentsinvoice.payment_failed— flags billing issues
Rate Limits
API requests are rate-limited per workspace to ensure fair usage:
| Plan | Rate Limit | Burst |
|---|---|---|
| Free | 60 req/min | 10 req/s |
| Pro | 300 req/min | 30 req/s |
| Business | 1000 req/min | 100 req/s |
Rate-limited responses return 429 Too Many Requests with a Retry-After header.