{ "openapi": "3.0.3", "info": { "title": "Notifuse API", "description": "API for Notifuse - a transactional email and newsletter management platform", "version": "1.0.0", "contact": { "name": "Notifuse Support", "url": "https://www.notifuse.com/support", "email": "hello@notifuse.com" } }, "servers": [ { "url": "https://{notifuseDomain}", "description": "Customer-specific Notifuse API server", "variables": { "notifuseDomain": { "description": "Your unique Notifuse domain", "default": "demo.notifuse.com" } } } ], "paths": { "/api/transactional.send": { "post": { "summary": "Send a transactional notification", "description": "Sends a transactional notification to a contact through specified channels.\nRequires authentication.", "operationId": "sendTransactionalNotification", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SendTransactionalRequest" } } } }, "responses": { "200": { "description": "Notification sent successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "message_id": { "type": "string", "description": "Unique identifier for the sent message", "example": "msg_1234567890abcdef" }, "success": { "type": "boolean", "description": "Whether the notification was sent successfully", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "notFoundExample": { "value": { "error": "Notification not found" } }, "inactiveExample": { "value": { "error": "Notification is not active" } }, "noChannelsExample": { "value": { "error": "No valid channels configured" } }, "validationExample": { "value": { "error": "notification.contact is required" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Unauthorized" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to send notification" } } } } } } }, "/api/contacts.upsert": { "post": { "summary": "Create or update a contact", "description": "Creates a new contact or updates an existing one based on email address. Returns information about whether the contact was created or updated.", "operationId": "upsertContact", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpsertContactRequest" } } } }, "responses": { "200": { "description": "Contact upserted successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpsertContactResponse" } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "workspace_id is required" } }, "invalidEmail": { "value": { "error": "invalid email format" } }, "missingContact": { "value": { "error": "contact is required" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/contacts.getByEmail": { "get": { "summary": "Get a contact by email address", "description": "Retrieves a contact by their email address within a specific workspace. The response always includes the contact's list subscriptions with their status (active, pending, unsubscribed, bounced, complained).", "operationId": "getContactByEmail", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "email", "in": "query", "required": true, "schema": { "type": "string", "format": "email" }, "description": "The email address of the contact", "example": "user@example.com" } ], "responses": { "200": { "description": "Contact found successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "contact": { "$ref": "#/components/schemas/Contact" } } } } } }, "400": { "description": "Bad request - missing parameters", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "Missing workspace ID" } }, "missingEmail": { "value": { "error": "Missing email" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Contact not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Contact not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/contacts.getByExternalID": { "get": { "summary": "Get a contact by external ID", "description": "Retrieves a contact by their external ID within a specific workspace. The response always includes the contact's list subscriptions with their status (active, pending, unsubscribed, bounced, complained).", "operationId": "getContactByExternalID", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "external_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The external ID of the contact", "example": "user_12345" } ], "responses": { "200": { "description": "Contact found successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "contact": { "$ref": "#/components/schemas/Contact" } } } } } }, "400": { "description": "Bad request - missing parameters", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "Missing workspace ID" } }, "missingExternalId": { "value": { "error": "Missing external ID" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Contact not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Contact not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/contacts.import": { "post": { "summary": "Batch import contacts", "description": "Creates or updates multiple contacts in a single batch operation. This is significantly more efficient than individual upsert operations. Optionally subscribes all contacts to specified lists.", "operationId": "batchImportContacts", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchImportContactsRequest" } } } }, "responses": { "200": { "description": "Batch import completed (may include partial failures)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchImportContactsResponse" } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "workspace_id is required" } }, "missingContacts": { "value": { "error": "contacts is required" } }, "emptyContacts": { "value": { "error": "contacts array cannot be empty" } }, "insufficientPermissions": { "value": { "error": "write access to lists required when subscribe_to_lists is provided" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/contacts.delete": { "post": { "summary": "Delete a contact", "description": "Deletes a contact from the workspace by email address. This action is permanent and cannot be undone.", "operationId": "deleteContact", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteContactRequest" } } } }, "responses": { "200": { "description": "Contact deleted successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the deletion was successful", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "workspace_id is required" } }, "missingEmail": { "value": { "error": "email is required" } }, "invalidEmail": { "value": { "error": "invalid email format" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Contact not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Contact not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to delete contact" } } } } } } }, "/api/contactLists.updateStatus": { "post": { "summary": "Update contact list subscription status", "description": "Updates the subscription status of a contact in a specific list. Can set status to active, pending, unsubscribed, bounced, or complained.", "operationId": "updateContactListStatus", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateContactListStatusRequest" } } } }, "responses": { "200": { "description": "Status updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateContactListStatusResponse" } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "workspace_id is required" } }, "missingEmail": { "value": { "error": "email is required" } }, "missingListId": { "value": { "error": "list_id is required" } }, "invalidStatus": { "value": { "error": "invalid status value" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Contact list relationship not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "contact list not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.list": { "get": { "summary": "List broadcasts", "description": "Retrieves a list of broadcasts with pagination and optional filtering by status. Supports fetching template details for each variation.", "operationId": "listBroadcasts", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "status", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "draft", "scheduled", "sending", "paused", "sent", "cancelled", "failed", "testing", "test_completed", "winner_selected" ] }, "description": "Filter broadcasts by status" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 50 }, "description": "Maximum number of broadcasts to return", "example": 50 }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "default": 0 }, "description": "Number of broadcasts to skip for pagination", "example": 0 }, { "name": "with_templates", "in": "query", "required": false, "schema": { "type": "boolean", "default": false }, "description": "Include full template details for each variation", "example": false } ], "responses": { "200": { "description": "List of broadcasts retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BroadcastListResponse" } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "workspace_id is required" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to list broadcasts" } } } } } } }, "/api/broadcasts.get": { "get": { "summary": "Get a broadcast", "description": "Retrieves a single broadcast by ID. Optionally includes template details for each variation.", "operationId": "getBroadcast", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the broadcast", "example": "broadcast_12345" }, { "name": "with_templates", "in": "query", "required": false, "schema": { "type": "boolean", "default": false }, "description": "Include full template details for each variation", "example": false } ], "responses": { "200": { "description": "Broadcast retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "broadcast": { "$ref": "#/components/schemas/Broadcast" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Broadcast not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.create": { "post": { "summary": "Create a broadcast", "description": "Creates a new broadcast campaign. The broadcast is created in draft status unless scheduling is configured.", "operationId": "createBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateBroadcastRequest" } } } }, "responses": { "201": { "description": "Broadcast created successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "broadcast": { "$ref": "#/components/schemas/Broadcast" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingName": { "value": { "error": "name is required" } }, "missingList": { "value": { "error": "list is required" } }, "invalidTestSettings": { "value": { "error": "at least 2 variations are required for A/B testing" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to create broadcast" } } } } } } }, "/api/broadcasts.update": { "post": { "summary": "Update a broadcast", "description": "Updates an existing broadcast. Only broadcasts in draft, scheduled, or paused status can be updated.", "operationId": "updateBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "broadcast": { "$ref": "#/components/schemas/Broadcast" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "invalidStatus": { "value": { "error": "cannot update broadcast with status: sending" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Broadcast not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.schedule": { "post": { "summary": "Schedule a broadcast", "description": "Schedules a broadcast for sending either immediately or at a specified time. This endpoint is restricted in demo mode.", "operationId": "scheduleBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast scheduled successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingDateTime": { "value": { "error": "scheduled_date and scheduled_time are required when not sending immediately" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.pause": { "post": { "summary": "Pause a broadcast", "description": "Pauses a broadcast that is currently sending.", "operationId": "pauseBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PauseBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast paused successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.resume": { "post": { "summary": "Resume a broadcast", "description": "Resumes a paused broadcast.", "operationId": "resumeBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResumeBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast resumed successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.cancel": { "post": { "summary": "Cancel a broadcast", "description": "Cancels a scheduled broadcast.", "operationId": "cancelBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CancelBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast cancelled successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.sendToIndividual": { "post": { "summary": "Send broadcast to individual", "description": "Sends a broadcast to a single recipient for testing purposes. Optionally specify which template variation to send.", "operationId": "sendBroadcastToIndividual", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SendToIndividualRequest" } } } }, "responses": { "200": { "description": "Broadcast sent to individual successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.delete": { "post": { "summary": "Delete a broadcast", "description": "Deletes a broadcast. This action is permanent and cannot be undone.", "operationId": "deleteBroadcast", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteBroadcastRequest" } } } }, "responses": { "200": { "description": "Broadcast deleted successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Broadcast not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.getTestResults": { "get": { "summary": "Get A/B test results", "description": "Retrieves the performance metrics for all variations in an A/B test broadcast.", "operationId": "getBroadcastTestResults", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the broadcast", "example": "broadcast_12345" } ], "responses": { "200": { "description": "Test results retrieved successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestResultsResponse" } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to get test results" } } } } } } }, "/api/templates.list": { "get": { "summary": "List templates", "description": "Retrieves a list of all templates in the workspace. Supports optional filtering by category and channel.", "operationId": "listTemplates", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "category", "in": "query", "required": false, "schema": { "type": "string", "enum": [ "marketing", "transactional", "welcome", "opt_in", "unsubscribe", "bounce", "blocklist", "blog", "other" ] }, "description": "Filter templates by category" }, { "name": "channel", "in": "query", "required": false, "schema": { "type": "string", "enum": ["email", "web"] }, "description": "Filter templates by channel" } ], "responses": { "200": { "description": "List of templates retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "templates": { "type": "array", "items": { "$ref": "#/components/schemas/Template" } } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "workspace_id is required" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to get templates" } } } } } } }, "/api/templates.get": { "get": { "summary": "Get a template", "description": "Retrieves a single template by ID. Optionally specify a version number to retrieve a specific version.", "operationId": "getTemplate", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "workspace_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the workspace", "example": "ws_1234567890" }, { "name": "id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The ID of the template", "example": "welcome_email" }, { "name": "version", "in": "query", "required": false, "schema": { "type": "integer", "format": "int64" }, "description": "Specific version number (defaults to latest)", "example": 1 } ], "responses": { "200": { "description": "Template retrieved successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "template": { "$ref": "#/components/schemas/Template" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Template not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Template not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/templates.create": { "post": { "summary": "Create a template", "description": "Creates a new template. Each template must have a channel (email or web) with corresponding channel-specific content.", "operationId": "createTemplate", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateTemplateRequest" } } } }, "responses": { "201": { "description": "Template created successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "template": { "$ref": "#/components/schemas/Template" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "duplicateId": { "value": { "error": "Template id already exists" } }, "missingEmail": { "value": { "error": "email is required for channel 'email'" } }, "invalidId": { "value": { "error": "id must contain only letters, numbers, underscores, and hyphens" } } } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to create template" } } } } } } }, "/api/templates.update": { "post": { "summary": "Update a template", "description": "Updates an existing template. Creates a new version of the template.", "operationId": "updateTemplate", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateTemplateRequest" } } } }, "responses": { "200": { "description": "Template updated successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "template": { "$ref": "#/components/schemas/Template" } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Template not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Template not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to update template" } } } } } } }, "/api/templates.delete": { "post": { "summary": "Delete a template", "description": "Soft-deletes a template. The template will be marked as deleted but not removed from the database.", "operationId": "deleteTemplate", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeleteTemplateRequest" } } } }, "responses": { "200": { "description": "Template deleted successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Template not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Template not found" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to delete template" } } } } } } }, "/api/templates.compile": { "post": { "summary": "Compile template", "description": "Compiles an MJML template with provided data, returning the rendered HTML. Useful for previewing templates before saving.", "operationId": "compileTemplate", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompileTemplateRequest" } } } }, "responses": { "200": { "description": "Template compiled successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompileTemplateResponse" } } } }, "400": { "description": "Bad request - compilation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Compilation failed: Invalid MJML syntax" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/api/broadcasts.selectWinner": { "post": { "summary": "Select winning A/B test variation", "description": "Manually selects the winning variation for an A/B test broadcast. The winning variation will be sent to the remaining audience. This endpoint is restricted in demo mode.", "operationId": "selectBroadcastWinner", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SelectWinnerRequest" } } } }, "responses": { "200": { "description": "Winner selected successfully", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Unauthorized - invalid or missing authentication token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to select winner" } } } } } } }, "/subscribe": { "post": { "summary": "Subscribe to email lists", "description": "Subscribe a contact to one or more email lists. This is a public endpoint that doesn't require authentication. If the list has double opt-in enabled, a confirmation email will be sent.", "operationId": "subscribeToLists", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SubscribeToListsRequest" } } } }, "responses": { "200": { "description": "Subscription successful", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the subscription was successful", "example": true } } } } } }, "400": { "description": "Bad request - validation failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "examples": { "missingWorkspaceId": { "value": { "error": "workspace_id is required" } }, "invalidEmail": { "value": { "error": "invalid contact: invalid email format" } }, "missingListIds": { "value": { "error": "list_ids is required" } }, "listNotPublic": { "value": { "error": "list is not public" } } } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" }, "example": { "error": "Failed to subscribe to lists" } } } } } } } }, "components": { "securitySchemes": { "BearerAuth": { "type": "http", "scheme": "bearer", "description": "API token for authentication" } }, "schemas": { "ErrorResponse": { "type": "object", "properties": { "error": { "type": "string", "description": "Error message" } }, "required": ["error"] }, "SendTransactionalRequest": { "type": "object", "required": ["workspace_id", "notification"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "notification": { "$ref": "#/components/schemas/TransactionalNotificationSendParams" } } }, "TransactionalNotificationSendParams": { "type": "object", "required": ["id", "contact"], "properties": { "id": { "type": "string", "description": "ID of the notification to send", "example": "welcome_email" }, "external_id": { "type": "string", "nullable": true, "description": "External ID for idempotency checks", "example": "txn_12345" }, "contact": { "$ref": "#/components/schemas/Contact" }, "channels": { "type": "array", "description": "Specific channels to send through (if empty, use all configured channels)", "items": { "type": "string", "enum": ["email"] }, "example": ["email"] }, "data": { "type": "object", "additionalProperties": true, "description": "Data to populate the template with", "example": { "user_name": "John Doe", "activation_link": "https://example.com/activate/abc123" } }, "metadata": { "type": "object", "additionalProperties": true, "description": "Additional metadata for tracking", "example": { "campaign_id": "spring_promo_2023", "source": "user_signup" } }, "email_options": { "type": "object", "description": "Email-specific options", "properties": { "from_name": { "type": "string", "nullable": true, "description": "Override default sender from name", "example": "Support Team" }, "cc": { "type": "array", "description": "CC email addresses", "items": { "type": "string", "format": "email" }, "example": ["manager@example.com"] }, "bcc": { "type": "array", "description": "BCC email addresses", "items": { "type": "string", "format": "email" }, "example": ["archive@example.com"] }, "reply_to": { "type": "string", "format": "email", "description": "Reply-To email address", "example": "support@example.com" }, "attachments": { "type": "array", "description": "Email attachments (max 20 files, 3MB per file, 10MB total)", "items": { "$ref": "#/components/schemas/EmailAttachment" }, "maxItems": 20, "example": [ { "filename": "invoice.pdf", "content": "JVBERi0xLjQKJeLjz9MKMy4uLg==", "content_type": "application/pdf", "disposition": "attachment" } ] } } } } }, "Contact": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email", "description": "Email address of the contact", "example": "user@example.com" }, "external_id": { "type": "string", "nullable": true, "description": "External identifier for the contact", "example": "user_12345" }, "timezone": { "type": "string", "nullable": true, "description": "Timezone of the contact", "example": "America/New_York" }, "language": { "type": "string", "nullable": true, "description": "Preferred language of the contact", "example": "en-US" }, "first_name": { "type": "string", "nullable": true, "description": "First name of the contact", "example": "John" }, "last_name": { "type": "string", "nullable": true, "description": "Last name of the contact", "example": "Doe" }, "phone": { "type": "string", "nullable": true, "description": "Phone number of the contact", "example": "+15551234567" }, "address_line_1": { "type": "string", "nullable": true, "description": "First line of address", "example": "123 Main St" }, "address_line_2": { "type": "string", "nullable": true, "description": "Second line of address", "example": "Apt 4B" }, "country": { "type": "string", "nullable": true, "description": "Country of the contact", "example": "US" }, "postcode": { "type": "string", "nullable": true, "description": "Postal code", "example": "10001" }, "state": { "type": "string", "nullable": true, "description": "State or province", "example": "NY" }, "job_title": { "type": "string", "nullable": true, "description": "Job title of the contact", "example": "Software Engineer" }, "lifetime_value": { "type": "number", "format": "float", "nullable": true, "description": "Lifetime value of the contact", "example": 1250.5 }, "orders_count": { "type": "number", "format": "float", "nullable": true, "description": "Number of orders placed by the contact", "example": 5 }, "last_order_at": { "type": "string", "format": "date-time", "nullable": true, "description": "Date and time of the contact's last order", "example": "2023-05-15T14:30:00Z" }, "custom_string_1": { "type": "string", "nullable": true, "description": "Custom string field 1", "example": "Premium tier" }, "custom_string_2": { "type": "string", "nullable": true, "description": "Custom string field 2" }, "custom_string_3": { "type": "string", "nullable": true, "description": "Custom string field 3" }, "custom_string_4": { "type": "string", "nullable": true, "description": "Custom string field 4" }, "custom_string_5": { "type": "string", "nullable": true, "description": "Custom string field 5" }, "custom_number_1": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 1", "example": 42 }, "custom_number_2": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 2" }, "custom_number_3": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 3" }, "custom_number_4": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 4" }, "custom_number_5": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 5" }, "custom_datetime_1": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 1", "example": "2023-06-01T09:00:00Z" }, "custom_datetime_2": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 2" }, "custom_datetime_3": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 3" }, "custom_datetime_4": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 4" }, "custom_datetime_5": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 5" }, "custom_json_1": { "type": "object", "nullable": true, "description": "Custom JSON field 1", "example": { "preferences": { "theme": "dark", "notifications": true } } }, "custom_json_2": { "type": "object", "nullable": true, "description": "Custom JSON field 2" }, "custom_json_3": { "type": "object", "nullable": true, "description": "Custom JSON field 3" }, "custom_json_4": { "type": "object", "nullable": true, "description": "Custom JSON field 4" }, "custom_json_5": { "type": "object", "nullable": true, "description": "Custom JSON field 5" }, "created_at": { "type": "string", "format": "date-time", "description": "When the contact was created", "example": "2023-01-15T10:30:00Z" }, "updated_at": { "type": "string", "format": "date-time", "description": "When the contact was last updated", "example": "2023-04-22T15:45:00Z" }, "contact_lists": { "type": "array", "description": "Lists the contact is subscribed to (only included in GET endpoints)", "items": { "$ref": "#/components/schemas/ContactList" }, "example": [ { "email": "user@example.com", "list_id": "newsletter", "list_name": "Newsletter", "status": "active", "created_at": "2023-01-15T10:30:00Z", "updated_at": "2023-01-15T10:30:00Z", "deleted_at": null } ] } } }, "ContactList": { "type": "object", "properties": { "email": { "type": "string", "format": "email", "description": "Email address of the contact", "example": "user@example.com" }, "list_id": { "type": "string", "description": "ID of the list", "example": "newsletter" }, "list_name": { "type": "string", "description": "Name of the list", "example": "Newsletter" }, "status": { "type": "string", "enum": ["active", "pending", "unsubscribed", "bounced", "complained"], "description": "Subscription status", "example": "active" }, "created_at": { "type": "string", "format": "date-time", "description": "When the contact was subscribed to this list", "example": "2023-01-15T10:30:00Z" }, "updated_at": { "type": "string", "format": "date-time", "description": "When the subscription was last updated", "example": "2023-01-15T10:30:00Z" }, "deleted_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the subscription was deleted (null if active)", "example": null } } }, "SubscribeToListsRequest": { "type": "object", "required": ["workspace_id", "contact", "list_ids"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "contact": { "$ref": "#/components/schemas/SubscriptionContact" }, "list_ids": { "type": "array", "description": "Array of list IDs to subscribe the contact to", "items": { "type": "string" }, "example": ["newsletter", "product_updates"], "minItems": 1 } } }, "SubscriptionContact": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email", "description": "Email address of the contact", "example": "user@example.com" }, "email_hmac": { "type": "string", "description": "HMAC of the email for authenticated subscription (optional)", "example": "a1b2c3d4e5f6..." }, "external_id": { "type": "string", "nullable": true, "description": "External identifier for the contact", "example": "user_12345" }, "timezone": { "type": "string", "nullable": true, "description": "Timezone of the contact", "example": "America/New_York" }, "language": { "type": "string", "nullable": true, "description": "Preferred language of the contact", "example": "en-US" }, "first_name": { "type": "string", "nullable": true, "description": "First name of the contact", "example": "John" }, "last_name": { "type": "string", "nullable": true, "description": "Last name of the contact", "example": "Doe" }, "phone": { "type": "string", "nullable": true, "description": "Phone number of the contact", "example": "+15551234567" }, "address_line_1": { "type": "string", "nullable": true, "description": "First line of address", "example": "123 Main St" }, "address_line_2": { "type": "string", "nullable": true, "description": "Second line of address", "example": "Apt 4B" }, "country": { "type": "string", "nullable": true, "description": "Country of the contact", "example": "US" }, "postcode": { "type": "string", "nullable": true, "description": "Postal code", "example": "10001" }, "state": { "type": "string", "nullable": true, "description": "State or province", "example": "NY" }, "job_title": { "type": "string", "nullable": true, "description": "Job title of the contact", "example": "Software Engineer" }, "lifetime_value": { "type": "number", "format": "float", "nullable": true, "description": "Lifetime value of the contact", "example": 1250.5 }, "orders_count": { "type": "number", "format": "float", "nullable": true, "description": "Number of orders placed by the contact", "example": 5 }, "last_order_at": { "type": "string", "format": "date-time", "nullable": true, "description": "Date and time of the contact's last order", "example": "2023-05-15T14:30:00Z" }, "custom_string_1": { "type": "string", "nullable": true, "description": "Custom string field 1", "example": "Premium tier" }, "custom_string_2": { "type": "string", "nullable": true, "description": "Custom string field 2" }, "custom_string_3": { "type": "string", "nullable": true, "description": "Custom string field 3" }, "custom_string_4": { "type": "string", "nullable": true, "description": "Custom string field 4" }, "custom_string_5": { "type": "string", "nullable": true, "description": "Custom string field 5" }, "custom_number_1": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 1", "example": 42 }, "custom_number_2": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 2" }, "custom_number_3": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 3" }, "custom_number_4": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 4" }, "custom_number_5": { "type": "number", "format": "float", "nullable": true, "description": "Custom number field 5" }, "custom_datetime_1": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 1", "example": "2023-06-01T09:00:00Z" }, "custom_datetime_2": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 2" }, "custom_datetime_3": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 3" }, "custom_datetime_4": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 4" }, "custom_datetime_5": { "type": "string", "format": "date-time", "nullable": true, "description": "Custom datetime field 5" }, "custom_json_1": { "type": "object", "nullable": true, "description": "Custom JSON field 1", "example": { "preferences": { "theme": "dark", "notifications": true } } }, "custom_json_2": { "type": "object", "nullable": true, "description": "Custom JSON field 2" }, "custom_json_3": { "type": "object", "nullable": true, "description": "Custom JSON field 3" }, "custom_json_4": { "type": "object", "nullable": true, "description": "Custom JSON field 4" }, "custom_json_5": { "type": "object", "nullable": true, "description": "Custom JSON field 5" } } }, "UpsertContactRequest": { "type": "object", "required": ["workspace_id", "contact"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "contact": { "$ref": "#/components/schemas/Contact" } } }, "UpsertContactResponse": { "type": "object", "properties": { "action": { "type": "string", "enum": ["created", "updated", "unchanged"], "description": "The action that was performed on the contact", "example": "created" }, "contact": { "$ref": "#/components/schemas/Contact" }, "error": { "type": "string", "nullable": true, "description": "Error message if the operation failed", "example": null } } }, "DeleteContactRequest": { "type": "object", "required": ["workspace_id", "email"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "email": { "type": "string", "format": "email", "description": "Email address of the contact to delete", "example": "user@example.com" } } }, "BatchImportContactsRequest": { "type": "object", "required": ["workspace_id", "contacts"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "contacts": { "type": "array", "description": "Array of contacts to import (create or update)", "items": { "$ref": "#/components/schemas/Contact" }, "minItems": 1, "example": [ { "email": "user1@example.com", "first_name": "John", "last_name": "Doe" }, { "email": "user2@example.com", "first_name": "Jane", "last_name": "Smith" } ] }, "subscribe_to_lists": { "type": "array", "description": "Optional array of list IDs to subscribe all contacts to", "items": { "type": "string" }, "example": ["newsletter", "product_updates"] } } }, "BatchImportContactsResponse": { "type": "object", "properties": { "operations": { "type": "array", "description": "Array of operation results, one for each contact in the request", "items": { "$ref": "#/components/schemas/UpsertContactOperation" } }, "error": { "type": "string", "nullable": true, "description": "Global error message if the entire operation failed", "example": null } } }, "UpsertContactOperation": { "type": "object", "properties": { "email": { "type": "string", "format": "email", "description": "Email address of the contact", "example": "user@example.com" }, "action": { "type": "string", "enum": ["create", "update", "error"], "description": "The action that was performed: 'create' for new contacts, 'update' for existing contacts, 'error' for failed operations", "example": "create" }, "error": { "type": "string", "nullable": true, "description": "Error message if this specific contact operation failed", "example": null } } }, "UpdateContactListStatusRequest": { "type": "object", "required": ["workspace_id", "email", "list_id", "status"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "email": { "type": "string", "format": "email", "description": "Email address of the contact", "example": "user@example.com" }, "list_id": { "type": "string", "description": "ID of the list", "example": "newsletter" }, "status": { "type": "string", "enum": ["active", "pending", "unsubscribed", "bounced", "complained"], "description": "New subscription status", "example": "active" } } }, "UpdateContactListStatusResponse": { "type": "object", "properties": { "success": { "type": "boolean", "description": "Whether the operation was successful", "example": true }, "message": { "type": "string", "description": "Status message", "example": "status updated successfully" }, "found": { "type": "boolean", "description": "Whether the contact was found in the list", "example": true } } }, "EmailAttachment": { "type": "object", "required": ["filename", "content"], "properties": { "filename": { "type": "string", "description": "Name of the file (max 255 characters, no path separators)", "example": "invoice.pdf", "maxLength": 255 }, "content": { "type": "string", "format": "byte", "description": "Base64-encoded file content (max 3MB per file)", "example": "JVBERi0xLjQKJeLjz9MKMy4uLg==" }, "content_type": { "type": "string", "description": "MIME type of the file (auto-detected if not provided)", "example": "application/pdf" }, "disposition": { "type": "string", "enum": ["attachment", "inline"], "description": "How the attachment should be displayed (defaults to 'attachment')", "example": "attachment", "default": "attachment" } } }, "Broadcast": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the broadcast", "example": "broadcast_12345" }, "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "name": { "type": "string", "description": "Name of the broadcast", "example": "Spring Newsletter 2024", "maxLength": 255 }, "channel_type": { "type": "string", "description": "Communication channel type", "example": "email" }, "status": { "type": "string", "enum": [ "draft", "scheduled", "sending", "paused", "sent", "cancelled", "failed", "testing", "test_completed", "winner_selected" ], "description": "Current status of the broadcast", "example": "draft" }, "audience": { "$ref": "#/components/schemas/AudienceSettings" }, "schedule": { "$ref": "#/components/schemas/ScheduleSettings" }, "test_settings": { "$ref": "#/components/schemas/BroadcastTestSettings" }, "utm_parameters": { "$ref": "#/components/schemas/UTMParameters" }, "metadata": { "type": "object", "additionalProperties": true, "description": "Custom metadata for the broadcast" }, "winning_template": { "type": "string", "nullable": true, "description": "ID of the winning template variation", "example": "template_winner" }, "test_sent_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the A/B test was sent" }, "winner_sent_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the winning variation was sent" }, "test_phase_recipient_count": { "type": "integer", "description": "Number of recipients in test phase" }, "winner_phase_recipient_count": { "type": "integer", "description": "Number of recipients in winner phase" }, "created_at": { "type": "string", "format": "date-time", "description": "When the broadcast was created" }, "updated_at": { "type": "string", "format": "date-time", "description": "When the broadcast was last updated" }, "started_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the broadcast started sending" }, "completed_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the broadcast completed sending" }, "cancelled_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the broadcast was cancelled" }, "paused_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the broadcast was paused" }, "pause_reason": { "type": "string", "nullable": true, "description": "Reason for pausing the broadcast" }, "sent_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the broadcast was sent" } } }, "BroadcastTestSettings": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether A/B testing is enabled", "example": true }, "sample_percentage": { "type": "integer", "minimum": 1, "maximum": 100, "description": "Percentage of audience to use for testing", "example": 20 }, "auto_send_winner": { "type": "boolean", "description": "Automatically send winning variation to remaining audience", "example": true }, "auto_send_winner_metric": { "type": "string", "enum": ["open_rate", "click_rate"], "description": "Metric used to determine the winner", "example": "open_rate" }, "test_duration_hours": { "type": "integer", "minimum": 1, "maximum": 168, "description": "Duration of the test in hours (max 7 days)", "example": 24 }, "variations": { "type": "array", "description": "Test variations (2-8 variations allowed)", "minItems": 2, "maxItems": 8, "items": { "$ref": "#/components/schemas/BroadcastVariation" } } } }, "BroadcastVariation": { "type": "object", "properties": { "variation_name": { "type": "string", "description": "Name of this variation", "example": "Variation A" }, "template_id": { "type": "string", "description": "Template ID for this variation", "example": "template_variant_a" }, "metrics": { "$ref": "#/components/schemas/VariationMetrics" }, "template": { "type": "object", "nullable": true, "description": "Full template object (populated when with_templates=true)" } }, "required": ["template_id"] }, "VariationMetrics": { "type": "object", "properties": { "recipients": { "type": "integer", "description": "Number of recipients" }, "delivered": { "type": "integer", "description": "Number of delivered messages" }, "opens": { "type": "integer", "description": "Number of opens" }, "clicks": { "type": "integer", "description": "Number of clicks" }, "bounced": { "type": "integer", "description": "Number of bounces" }, "complained": { "type": "integer", "description": "Number of complaints" }, "unsubscribed": { "type": "integer", "description": "Number of unsubscribes" } } }, "AudienceSettings": { "type": "object", "required": ["lists"], "properties": { "lists": { "type": "array", "description": "List IDs to send to (at least one required)", "items": { "type": "string" }, "minItems": 1, "example": ["newsletter", "customers"] }, "segments": { "type": "array", "description": "Optional segment IDs to filter recipients", "items": { "type": "string" }, "example": ["premium_users"] }, "exclude_unsubscribed": { "type": "boolean", "description": "Whether to exclude unsubscribed contacts", "example": true }, "skip_duplicate_emails": { "type": "boolean", "description": "Whether to skip duplicate email addresses", "example": true } } }, "ScheduleSettings": { "type": "object", "properties": { "is_scheduled": { "type": "boolean", "description": "Whether the broadcast is scheduled", "example": true }, "scheduled_date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Scheduled date in YYYY-MM-DD format", "example": "2024-03-15" }, "scheduled_time": { "type": "string", "pattern": "^\\d{2}:\\d{2}$", "description": "Scheduled time in HH:MM format", "example": "10:30" }, "timezone": { "type": "string", "description": "IANA timezone", "example": "America/New_York" }, "use_recipient_timezone": { "type": "boolean", "description": "Send at scheduled time in each recipient's timezone", "example": false } } }, "UTMParameters": { "type": "object", "properties": { "source": { "type": "string", "description": "UTM source parameter", "example": "newsletter" }, "medium": { "type": "string", "description": "UTM medium parameter", "example": "email" }, "campaign": { "type": "string", "description": "UTM campaign parameter", "example": "spring_2024" }, "term": { "type": "string", "description": "UTM term parameter" }, "content": { "type": "string", "description": "UTM content parameter" } } }, "CreateBroadcastRequest": { "type": "object", "required": ["workspace_id", "name", "audience"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "name": { "type": "string", "description": "Name of the broadcast", "example": "Spring Newsletter 2024", "maxLength": 255 }, "audience": { "$ref": "#/components/schemas/AudienceSettings" }, "schedule": { "$ref": "#/components/schemas/ScheduleSettings" }, "test_settings": { "$ref": "#/components/schemas/BroadcastTestSettings" }, "tracking_enabled": { "type": "boolean", "description": "Enable click and open tracking", "example": true }, "utm_parameters": { "$ref": "#/components/schemas/UTMParameters" }, "metadata": { "type": "object", "additionalProperties": true, "description": "Custom metadata for the broadcast" } } }, "UpdateBroadcastRequest": { "type": "object", "required": ["workspace_id", "id", "name", "audience"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to update", "example": "broadcast_12345" }, "name": { "type": "string", "description": "Name of the broadcast", "example": "Spring Newsletter 2024", "maxLength": 255 }, "audience": { "$ref": "#/components/schemas/AudienceSettings" }, "schedule": { "$ref": "#/components/schemas/ScheduleSettings" }, "test_settings": { "$ref": "#/components/schemas/BroadcastTestSettings" }, "tracking_enabled": { "type": "boolean", "description": "Enable click and open tracking", "example": true }, "utm_parameters": { "$ref": "#/components/schemas/UTMParameters" }, "metadata": { "type": "object", "additionalProperties": true, "description": "Custom metadata for the broadcast" } } }, "ScheduleBroadcastRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to schedule", "example": "broadcast_12345" }, "send_now": { "type": "boolean", "description": "Send immediately instead of scheduling", "example": false }, "scheduled_date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "Scheduled date in YYYY-MM-DD format (required if send_now=false)", "example": "2024-03-15" }, "scheduled_time": { "type": "string", "pattern": "^\\d{2}:\\d{2}$", "description": "Scheduled time in HH:MM format (required if send_now=false)", "example": "10:30" }, "timezone": { "type": "string", "description": "IANA timezone", "example": "America/New_York" }, "use_recipient_timezone": { "type": "boolean", "description": "Send at scheduled time in each recipient's timezone", "example": false } } }, "PauseBroadcastRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to pause", "example": "broadcast_12345" } } }, "ResumeBroadcastRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to resume", "example": "broadcast_12345" } } }, "CancelBroadcastRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to cancel", "example": "broadcast_12345" } } }, "DeleteBroadcastRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast to delete", "example": "broadcast_12345" } } }, "SendToIndividualRequest": { "type": "object", "required": ["workspace_id", "broadcast_id", "recipient_email"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "broadcast_id": { "type": "string", "description": "ID of the broadcast", "example": "broadcast_12345" }, "recipient_email": { "type": "string", "format": "email", "description": "Email address to send test to", "example": "test@example.com" }, "template_id": { "type": "string", "description": "Optional specific template variation to send", "example": "template_variant_a" } } }, "SelectWinnerRequest": { "type": "object", "required": ["workspace_id", "id", "template_id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the broadcast", "example": "broadcast_12345" }, "template_id": { "type": "string", "description": "Template ID of the winning variation", "example": "template_variant_a" } } }, "BroadcastListResponse": { "type": "object", "properties": { "broadcasts": { "type": "array", "description": "List of broadcasts", "items": { "$ref": "#/components/schemas/Broadcast" } }, "total_count": { "type": "integer", "description": "Total number of broadcasts matching the query", "example": 45 } } }, "VariationResult": { "type": "object", "properties": { "template_id": { "type": "string", "description": "Template ID for this variation", "example": "template_variant_a" }, "template_name": { "type": "string", "description": "Template name", "example": "Variation A" }, "recipients": { "type": "integer", "description": "Total sent emails", "example": 1000 }, "delivered": { "type": "integer", "description": "Total delivered emails", "example": 980 }, "opens": { "type": "integer", "description": "Number of opens", "example": 450 }, "clicks": { "type": "integer", "description": "Number of clicks", "example": 120 }, "open_rate": { "type": "number", "format": "float", "description": "Open rate (opens / recipients)", "example": 0.45 }, "click_rate": { "type": "number", "format": "float", "description": "Click rate (clicks / recipients)", "example": 0.12 } } }, "TestResultsResponse": { "type": "object", "properties": { "broadcast_id": { "type": "string", "description": "ID of the broadcast", "example": "broadcast_12345" }, "status": { "type": "string", "description": "Current broadcast status", "example": "testing" }, "test_started_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the test started" }, "test_completed_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the test completed" }, "variation_results": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/VariationResult" }, "description": "Results for each variation, keyed by template_id" }, "recommended_winner": { "type": "string", "nullable": true, "description": "Recommended winning template ID based on metrics", "example": "template_variant_a" }, "winning_template": { "type": "string", "nullable": true, "description": "Selected winning template ID", "example": "template_variant_a" }, "is_auto_send_winner": { "type": "boolean", "description": "Whether winner will be automatically sent", "example": true } } }, "Template": { "type": "object", "properties": { "id": { "type": "string", "description": "Unique identifier for the template (alphanumeric, underscores, and hyphens only)", "example": "welcome_email", "maxLength": 32, "pattern": "^[a-zA-Z0-9_-]+$" }, "name": { "type": "string", "description": "Name of the template", "example": "Welcome Email", "maxLength": 32 }, "version": { "type": "integer", "format": "int64", "description": "Version number of the template", "example": 1 }, "channel": { "type": "string", "enum": ["email", "web"], "description": "Communication channel", "example": "email" }, "email": { "$ref": "#/components/schemas/EmailTemplate" }, "web": { "$ref": "#/components/schemas/WebTemplate" }, "category": { "type": "string", "enum": [ "marketing", "transactional", "welcome", "opt_in", "unsubscribe", "bounce", "blocklist", "blog", "other" ], "description": "Template category", "example": "transactional", "maxLength": 20 }, "template_macro_id": { "type": "string", "nullable": true, "description": "ID of the template macro (layout) to use" }, "integration_id": { "type": "string", "nullable": true, "description": "ID of the integration managing this template (e.g., Supabase)" }, "test_data": { "type": "object", "additionalProperties": true, "description": "Test data for template preview", "example": { "user_name": "John Doe", "action_url": "https://example.com/action" } }, "settings": { "type": "object", "additionalProperties": true, "description": "Channel-specific third-party settings" }, "created_at": { "type": "string", "format": "date-time", "description": "When the template was created" }, "updated_at": { "type": "string", "format": "date-time", "description": "When the template was last updated" }, "deleted_at": { "type": "string", "format": "date-time", "nullable": true, "description": "When the template was deleted (null if active)" } }, "required": ["id", "name", "channel", "category"] }, "EmailTemplate": { "type": "object", "properties": { "sender_id": { "type": "string", "description": "ID of the sender configuration to use", "example": "sender_123" }, "reply_to": { "type": "string", "format": "email", "description": "Reply-To email address", "example": "support@example.com" }, "subject": { "type": "string", "description": "Email subject line (supports Liquid templating)", "example": "Welcome, {{user_name}}!" }, "subject_preview": { "type": "string", "nullable": true, "description": "Preview text shown in email clients", "example": "Get started with your account" }, "compiled_preview": { "type": "string", "description": "Compiled HTML preview of the email" }, "visual_editor_tree": { "type": "object", "description": "MJML visual editor tree structure", "example": { "type": "mjml", "children": [] } } }, "required": ["subject", "compiled_preview", "visual_editor_tree"] }, "WebTemplate": { "type": "object", "properties": { "content": { "type": "object", "additionalProperties": true, "description": "Tiptap JSON content (source of truth for web templates)" }, "html": { "type": "string", "description": "Pre-rendered HTML for display" }, "plain_text": { "type": "string", "description": "Extracted text for search indexing" } }, "required": ["content"] }, "CreateTemplateRequest": { "type": "object", "required": ["workspace_id", "id", "name", "channel", "category"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "Unique identifier for the template (alphanumeric, underscores, and hyphens only)", "example": "welcome_email", "maxLength": 32, "pattern": "^[a-zA-Z0-9_-]+$" }, "name": { "type": "string", "description": "Name of the template", "example": "Welcome Email", "maxLength": 32 }, "channel": { "type": "string", "enum": ["email", "web"], "description": "Communication channel", "example": "email" }, "email": { "$ref": "#/components/schemas/EmailTemplate" }, "web": { "$ref": "#/components/schemas/WebTemplate" }, "category": { "type": "string", "enum": [ "marketing", "transactional", "welcome", "opt_in", "unsubscribe", "bounce", "blocklist", "blog", "other" ], "description": "Template category", "example": "transactional" }, "template_macro_id": { "type": "string", "nullable": true, "description": "ID of the template macro (layout) to use" }, "test_data": { "type": "object", "additionalProperties": true, "description": "Test data for template preview" }, "settings": { "type": "object", "additionalProperties": true, "description": "Channel-specific settings" } } }, "UpdateTemplateRequest": { "type": "object", "required": ["workspace_id", "id", "name", "channel", "category"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the template to update", "example": "welcome_email", "maxLength": 32 }, "name": { "type": "string", "description": "Name of the template", "example": "Welcome Email", "maxLength": 32 }, "channel": { "type": "string", "enum": ["email", "web"], "description": "Communication channel", "example": "email" }, "email": { "$ref": "#/components/schemas/EmailTemplate" }, "web": { "$ref": "#/components/schemas/WebTemplate" }, "category": { "type": "string", "enum": [ "marketing", "transactional", "welcome", "opt_in", "unsubscribe", "bounce", "blocklist", "blog", "other" ], "description": "Template category", "example": "transactional" }, "template_macro_id": { "type": "string", "nullable": true, "description": "ID of the template macro (layout) to use" }, "test_data": { "type": "object", "additionalProperties": true, "description": "Test data for template preview" }, "settings": { "type": "object", "additionalProperties": true, "description": "Channel-specific settings" } } }, "DeleteTemplateRequest": { "type": "object", "required": ["workspace_id", "id"], "properties": { "workspace_id": { "type": "string", "description": "The ID of the workspace", "example": "ws_1234567890" }, "id": { "type": "string", "description": "ID of the template to delete", "example": "welcome_email" } } }, "CompileTemplateRequest": { "type": "object", "required": ["template_content", "template_data"], "properties": { "template_content": { "type": "object", "description": "MJML template structure to compile", "additionalProperties": true }, "template_data": { "type": "object", "description": "Data to use for Liquid templating", "additionalProperties": true, "example": { "user_name": "John Doe", "action_url": "https://example.com/action" } } } }, "CompileTemplateResponse": { "type": "object", "properties": { "html": { "type": "string", "description": "Compiled HTML output" }, "errors": { "type": "array", "description": "Compilation errors, if any", "items": { "type": "string" } } } } } } }