openapi: 3.2.0 info: title: Relay External REST Campaigns API version: 1.1.0 description: REST API for programmatic access to Relay CRM resources. servers: - url: https://your-domain.com/api/v1 description: Production security: - bearerAuth: [] tags: - name: Campaigns paths: /campaigns: get: summary: List campaigns tags: - Campaigns parameters: - name: status in: query schema: type: string enum: - draft - scheduled - sending - sent - cancelled - failed - name: limit in: query description: Max results (default 50). schema: type: integer minimum: 1 maximum: 100 - name: offset in: query description: Pagination offset (default 0). schema: type: integer minimum: 0 responses: '200': description: Success content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Campaign' meta: $ref: '#/components/schemas/PaginationMeta' required: - data '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: getCampaigns x-operation-id-source: derived post: summary: Create campaign tags: - Campaigns requestBody: required: true description: name (required); subject, body_html, body_text, list_id, view_id, integration_id, from_name, from_email, reply_to_email content: application/json: schema: type: object additionalProperties: true responses: '201': description: Created content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/Campaign' required: - data '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: postCampaigns x-operation-id-source: derived /campaigns/{id}: get: summary: Get campaign tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid responses: '200': description: Success content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/Campaign' required: - data '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: getCampaignsById x-operation-id-source: derived patch: summary: Update campaign (draft/scheduled only) tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true description: Content/audience/integration fields content: application/json: schema: type: object additionalProperties: true responses: '200': description: Success content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/Campaign' required: - data '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: patchCampaignsById x-operation-id-source: derived delete: summary: Delete campaign (draft only) tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid responses: '204': description: No content '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: deleteCampaignsById x-operation-id-source: derived /campaigns/{id}/schedule: post: summary: Schedule campaign tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true description: scheduled_at (ISO datetime) content: application/json: schema: type: object additionalProperties: true responses: '200': description: Success content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/Campaign' required: - data '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: postCampaignsByIdSchedule x-operation-id-source: derived /campaigns/{id}/send: post: summary: Send campaign now tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid responses: '200': description: Success content: application/json: schema: type: object properties: data: type: object properties: queued: type: integer scheduled: type: boolean total_recipients: type: integer '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: postCampaignsByIdSend x-operation-id-source: derived /campaigns/{id}/cancel: post: summary: Cancel campaign tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid responses: '200': description: Success content: application/json: schema: type: object properties: data: type: object '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: postCampaignsByIdCancel x-operation-id-source: derived /campaigns/{id}/test: post: summary: Send test email tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true description: test_email (required) content: application/json: schema: type: object additionalProperties: true responses: '200': description: Success content: application/json: schema: type: object properties: data: type: object properties: success: type: boolean message_id: type: string '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: postCampaignsByIdTest x-operation-id-source: derived /campaigns/{id}/stats: get: summary: Campaign stats tags: - Campaigns parameters: - name: id in: path required: true schema: type: string format: uuid responses: '200': description: Success content: application/json: schema: type: object properties: data: type: object properties: total_recipients: type: integer total_sent: type: integer total_opened: type: integer total_clicked: type: integer total_bounced: type: integer total_failed: type: integer '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '403': description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' operationId: getCampaignsByIdStats x-operation-id-source: derived components: schemas: Campaign: type: object properties: id: type: string organization_id: type: string name: type: string subject: type: - string - 'null' status: type: string enum: - draft - scheduled - sending - sent - cancelled - failed list_id: type: - string - 'null' view_id: type: - string - 'null' integration_id: type: - string - 'null' scheduled_at: type: - string - 'null' format: date-time total_recipients: type: integer total_sent: type: integer total_opened: type: integer total_clicked: type: integer created_at: type: string format: date-time ErrorResponse: type: object properties: error: type: object properties: code: type: string message: type: string details: {} required: - code - message required: - error PaginationMeta: type: object properties: total: type: integer limit: type: integer next_cursor: type: - string - 'null' securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: API Key