Modality
Documentation

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
API keys are scoped to a workspace. Generate them in Settings → API. Each key has full access to the workspace data.
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.

GET/api/v1/contactsAuth Required

List all contacts in the workspace. Supports pagination, sorting, and filtering.

Query Parameters
workspaceIdstringrequiredWorkspace ID
pageSizenumberItems per page (default: 50)
pagenumberPage number (default: 1)
sortBystringSort field (default: createdAt)
sortDirectionasc|descSort direction (default: desc)
searchstringSearch by name or email
tagstringFilter by tag slug
listIdstringFilter by list ID
Response
{
  "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
}
POST/api/v1/contactsAuth Required

Create a new contact or upsert by email.

Request Body (JSON)
emailstringrequiredContact email address
firstNamestringFirst name
lastNamestringLast name
phonestringPhone number
sourcestringLead source identifier
tagIdsstring[]Array of tag IDs to attach
Response
{ "data": { "id": "clx...", "email": "user@example.com", ... } }
GET/api/v1/contacts/:idAuth Required

Get 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"
  }
}
PATCH/api/v1/contacts/:idAuth Required

Update a contact's fields. Supports adding/removing tags.

Request Body (JSON)
firstNamestringUpdated first name
lastNamestringUpdated last name
phonestringUpdated phone
addTagIdstringTag ID to add
removeTagIdstringTag ID to remove
POST/api/v1/contacts/importAuth Required

Bulk import contacts from CSV data.

Request Body (JSON)
contactsobject[]requiredArray of contact objects with mapped fields
tagIdsstring[]Tags to apply to all imported contacts
Response
{ "data": { "imported": 150, "updated": 23, "errors": 2 } }

Events

Create and manage events with ticket types.

GET/api/v1/eventsAuth Required

List all events in the workspace.

Query Parameters
workspaceIdstringrequiredWorkspace ID
statusstringFilter by status: DRAFT, PUBLISHED, CANCELLED
Response
{
  "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
}
POST/api/v1/eventsAuth Required

Create a new event.

Request Body (JSON)
titlestringrequiredEvent title
descriptionstringEvent description (supports markdown)
startsAtISO 8601requiredEvent start date/time
endsAtISO 8601Event end date/time
venuestringVenue name
addressstringVenue address
statusstringDRAFT or PUBLISHED (default: DRAFT)
POST/api/v1/events/:id/ticket-typesAuth Required

Add 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 available
descriptionstringTicket type description
POST/api/v1/events/:id/checkout

Create a Stripe checkout session for ticket purchase. Public endpoint — no auth required.

Request Body (JSON)
emailstringrequiredBuyer email
firstNamestringBuyer first name
lastNamestringBuyer last name
itemsarrayrequired[ { ticketTypeId, quantity } ]
Response
{
  "data": {
    "checkoutUrl": "https://checkout.stripe.com/...",
    "orderId": "clx..."
  }
}

Forms

Manage forms and their submissions.

GET/api/v1/formsAuth Required

List all forms in the workspace.

Query Parameters
workspaceIdstringrequiredWorkspace ID
POST/api/v1/formsAuth Required

Create a new form.

Request Body (JSON)
namestringrequiredForm name
fieldsFormField[]Array of field definitions
settingsobjectForm settings (theme, payment, notifications)
statusstringDRAFT or PUBLISHED
POST/api/v1/submissions/:slug

Submit a form. Public endpoint. Creates/upserts contact and stores submission data.

Request Body (JSON)
(dynamic)objectrequiredForm field values keyed by field ID
Response
{
  "data": {
    "id": "clx...",
    "formId": "clx...",
    "contactId": "clx...",
    "paymentUrl": "https://..." // if payment form
  }
}

Campaigns

Create and manage email campaigns.

GET/api/v1/campaignsAuth Required

List all campaigns in the workspace.

Query Parameters
workspaceIdstringrequiredWorkspace ID
POST/api/v1/campaignsAuth Required

Create a new campaign.

Request Body (JSON)
namestringrequiredCampaign name
subjectstringrequiredEmail subject line
htmlContentstringHTML email content
textContentstringPlain text fallback
audienceTypestringALL, TAG, or LIST
audienceValuestringTag slug or list ID for targeting
connectorIdstringIntegration connector ID for delivery
POST/api/v1/campaigns/:id/sendAuth Required

Send or schedule a campaign for delivery.

Request Body (JSON)
scheduledForISO 8601Schedule send time (omit for immediate)

Automations

Manage workflow automations.

GET/api/v1/automationsAuth Required

List all automations in the workspace.

Query Parameters
workspaceIdstringrequiredWorkspace ID
POST/api/v1/automationsAuth Required

Create a new automation.

Request Body (JSON)
namestringrequiredAutomation name
triggerobjectrequired{ type, config } — trigger definition
actionsobject[]requiredArray of { type, config } action steps
statusstringACTIVE or PAUSED (default: ACTIVE)

Custom Objects

Create and manage custom data structures.

GET/api/v1/objectsAuth Required

List 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" }
      ]
    }
  ]
}
POST/api/v1/objectsAuth Required

Create a new object type.

Request Body (JSON)
namestringrequiredPlural name (e.g., Deals)
slugstringrequiredURL-safe identifier
singularNamestringSingular form (e.g., Deal)
iconstringLucide icon name
GET/api/v1/objects/:slug/recordsAuth Required

List records in an object type with sorting and filtering.

Query Parameters
pagenumberPage number
pageSizenumberItems per page
sortBystringAttribute to sort by
sortDirasc|descSort direction
searchstringFull-text search across attributes
POST/api/v1/objects/:slug/recordsAuth Required

Create a new record.

Request Body (JSON)
titlestringrequiredRecord title
attributesobjectKey-value pairs for custom attributes

Webhooks

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 email
  • customer.subscription.created — activates workspace subscription
  • customer.subscription.updated — handles plan changes
  • customer.subscription.deleted — handles cancellations
  • invoice.payment_succeeded — records successful payments
  • invoice.payment_failed — flags billing issues
Custom webhook endpoints for workspace events (contact created, form submitted, ticket purchased) are on the roadmap. Currently, use automations to react to these events.

Rate Limits

API requests are rate-limited per workspace to ensure fair usage:

PlanRate LimitBurst
Free60 req/min10 req/s
Pro300 req/min30 req/s
Business1000 req/min100 req/s

Rate-limited responses return 429 Too Many Requests with a Retry-After header.