Files
plunk/apps/wiki/openapi.json
T
2025-12-07 10:25:18 +01:00

1312 lines
39 KiB
JSON

{
"openapi": "3.1.0",
"info": {
"title": "Plunk API",
"description": "Open-source email platform API for transactional emails, campaigns, and marketing automation",
"version": "1.0.0",
"contact": {
"name": "Plunk Support",
"url": "https://useplunk.com"
}
},
"servers": [
{
"url": "https://api.useplunk.com",
"description": "Production server"
}
],
"security": [
{
"ApiKeyAuth": []
}
],
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "API Key",
"description": "API Key authentication. **Secret keys (sk_*)** are required for all endpoints except `/v1/track`. **Public keys (pk_*)** only work with the `/v1/track` endpoint for client-side event tracking. The project is automatically derived from the key."
}
},
"schemas": {
"Contact": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique contact identifier"
},
"email": {
"type": "string",
"format": "email",
"description": "Contact email address"
},
"subscribed": {
"type": "boolean",
"description": "Subscription status"
},
"data": {
"type": "object",
"description": "Custom contact data fields",
"additionalProperties": true
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"Template": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["TRANSACTIONAL", "MARKETING"]
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"Campaign": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["ALL", "SEGMENT", "FILTERED"]
},
"status": {
"type": "string",
"enum": ["DRAFT", "SCHEDULED", "SENDING", "SENT"]
},
"scheduledAt": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
},
"Segment": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"filters": {
"type": "object"
},
"trackMembership": {
"type": "boolean"
},
"memberCount": {
"type": "integer"
}
}
},
"Error": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"error": {
"type": "string"
},
"message": {
"type": "string"
},
"time": {
"type": "integer"
}
}
}
},
"parameters": {
"Limit": {
"name": "limit",
"in": "query",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 20
},
"description": "Maximum items per page"
},
"Cursor": {
"name": "cursor",
"in": "query",
"schema": {
"type": "string"
},
"description": "Pagination cursor"
}
}
},
"paths": {
"/v1/send": {
"post": {
"tags": ["Public API"],
"summary": "Send transactional email",
"description": "Send a transactional email via the public API. Automatically creates/updates contacts.",
"operationId": "sendEmail",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["to"],
"properties": {
"to": {
"oneOf": [
{
"type": "string",
"format": "email",
"description": "Simple email address"
},
{
"type": "object",
"required": ["email"],
"properties": {
"name": {
"type": "string",
"description": "Recipient display name"
},
"email": {
"type": "string",
"format": "email",
"description": "Recipient email address"
}
},
"description": "Recipient with name and email"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string",
"format": "email"
},
{
"type": "object",
"required": ["email"],
"properties": {
"name": {
"type": "string",
"description": "Recipient display name"
},
"email": {
"type": "string",
"format": "email",
"description": "Recipient email address"
}
}
}
]
},
"description": "Array of recipients (strings or objects)"
}
],
"description": "Recipient email(s). Can be a string, an object with {name, email}, or an array of either."
},
"subject": {
"type": "string",
"description": "Email subject (required if no template)"
},
"body": {
"type": "string",
"description": "Email body HTML (required if no template)"
},
"template": {
"type": "string",
"description": "Template ID to use for this email. When provided, uses the template's subject, body, from, and reply-to settings. You can override these by explicitly providing subject, body, from, or reply fields in the request. Template variables are populated from the data field."
},
"from": {
"oneOf": [
{
"type": "string",
"format": "email",
"description": "Simple email address"
},
{
"type": "object",
"required": ["email"],
"properties": {
"name": {
"type": "string",
"description": "Sender display name"
},
"email": {
"type": "string",
"format": "email",
"description": "Sender email address"
}
},
"description": "Sender with name and email"
}
],
"description": "Custom from address (requires verified domain). Can be a string or an object with {name, email}."
},
"name": {
"type": "string",
"description": "Sender display name (alternative to using from.name)"
},
"subscribed": {
"type": "boolean",
"description": "Whether recipient is subscribed to marketing emails. Defaults to false for transactional emails.",
"default": false
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "Template variables"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Custom email headers"
},
"reply": {
"type": "string",
"format": "email",
"description": "Reply-to address"
},
"attachments": {
"type": "array",
"description": "Email attachments (max 10 attachments, 10MB total)",
"maxItems": 10,
"items": {
"type": "object",
"required": ["filename", "content", "contentType"],
"properties": {
"filename": {
"type": "string",
"maxLength": 255,
"description": "Attachment filename"
},
"content": {
"type": "string",
"description": "Base64 encoded file content"
},
"contentType": {
"type": "string",
"maxLength": 255,
"description": "MIME type (e.g., application/pdf, image/png)"
}
}
}
}
}
},
"examples": {
"simple": {
"summary": "Simple transactional email",
"value": {
"to": "user@example.com",
"subject": "Password Reset Request",
"body": "<h1>Reset Your Password</h1><p>Click the link to reset: {{resetLink}}</p>",
"data": {
"resetLink": "https://example.com/reset/abc123"
}
}
},
"withNames": {
"summary": "Email with recipient and sender names",
"value": {
"to": {
"name": "Jane Doe",
"email": "jane@example.com"
},
"from": {
"name": "My Company",
"email": "hello@mycompany.com"
},
"subject": "Welcome to Our Service",
"body": "<h1>Welcome {{name}}!</h1><p>We're glad to have you.</p>",
"data": {
"name": "Jane"
}
}
},
"multipleRecipients": {
"summary": "Multiple recipients with names",
"value": {
"to": [
{
"name": "Jane Doe",
"email": "jane@example.com"
},
{
"name": "John Smith",
"email": "john@example.com"
}
],
"from": {
"name": "Newsletter",
"email": "news@mycompany.com"
},
"subject": "Monthly Update",
"body": "<h1>Hello {{name}}!</h1>"
}
},
"withTemplate": {
"summary": "Using a template",
"description": "Send email using a template. Provide the template ID and any data for template variables. The template's subject, body, from address, and reply-to will be used automatically.",
"value": {
"to": "user@example.com",
"template": "clx123abc456",
"data": {
"firstName": "John",
"lastName": "Doe",
"resetCode": {
"value": "ABC123",
"persistent": false
}
}
}
},
"withTemplateOverride": {
"summary": "Using template with overrides",
"description": "You can override template values by providing subject, body, from, or reply fields. This example overrides the template's subject line.",
"value": {
"to": "user@example.com",
"template": "clx123abc456",
"subject": "Custom Subject Override",
"data": {
"firstName": "Jane"
}
}
},
"marketingEmail": {
"summary": "Marketing email (set subscribed: true)",
"value": {
"to": "user@example.com",
"subject": "Weekly Newsletter",
"body": "<h1>This Week's Updates</h1>",
"subscribed": true
}
},
"withAttachment": {
"summary": "Email with PDF attachment",
"value": {
"to": "user@example.com",
"subject": "Your Invoice",
"body": "<h1>Invoice Attached</h1><p>Please find your invoice attached.</p>",
"attachments": [
{
"filename": "invoice.pdf",
"content": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL...",
"contentType": "application/pdf"
}
]
}
}
}
}
}
},
"responses": {
"200": {
"description": "Email queued successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"emails": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"to": {
"type": "string"
},
"status": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/v1/track": {
"post": {
"tags": ["Public API"],
"summary": "Track event",
"description": "Track an event for a contact. Automatically creates/updates the contact.",
"operationId": "trackEvent",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["email", "event"],
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Contact email"
},
"event": {
"type": "string",
"description": "Event name"
},
"subscribed": {
"type": "boolean",
"description": "Whether contact is subscribed to marketing emails. Defaults to true for event tracking.",
"default": true
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "Event data and contact metadata"
}
}
},
"example": {
"email": "user@example.com",
"event": "purchase",
"data": {
"product": "Premium Plan",
"amount": 99.0
}
}
}
}
},
"responses": {
"200": {
"description": "Event tracked successfully",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"contact": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"email": {
"type": "string"
}
}
},
"event": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"event": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
},
"/contacts": {
"get": {
"tags": ["Contacts"],
"summary": "List contacts",
"description": "Get a paginated list of contacts with cursor-based pagination",
"operationId": "listContacts",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"$ref": "#/components/parameters/Limit"
},
{
"$ref": "#/components/parameters/Cursor"
},
{
"name": "subscribed",
"in": "query",
"schema": {
"type": "boolean"
},
"description": "Filter by subscription status"
},
{
"name": "search",
"in": "query",
"schema": {
"type": "string"
},
"description": "Search by email"
}
],
"responses": {
"200": {
"description": "List of contacts",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Contact"
}
},
"nextCursor": {
"type": "string",
"nullable": true
},
"hasMore": {
"type": "boolean"
},
"total": {
"type": "integer"
}
}
}
}
}
}
}
}
}
},
"post": {
"tags": ["Contacts"],
"summary": "Create or update contact",
"description": "Create a new contact or update existing (upsert by email)",
"operationId": "createContact",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["email"],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"subscribed": {
"type": "boolean",
"default": true
},
"data": {
"type": "object",
"additionalProperties": true
}
}
},
"example": {
"email": "user@example.com",
"subscribed": true,
"data": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium"
}
}
}
}
},
"responses": {
"200": {
"description": "Contact created/updated",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Contact"
}
}
}
}
}
}
}
}
},
"/contacts/{id}": {
"get": {
"tags": ["Contacts"],
"summary": "Get contact",
"description": "Get a single contact by ID",
"operationId": "getContact",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Contact details",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Contact"
}
}
}
}
}
},
"404": {
"description": "Contact not found"
}
}
},
"patch": {
"tags": ["Contacts"],
"summary": "Update contact",
"description": "Update an existing contact",
"operationId": "updateContact",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"subscribed": {
"type": "boolean"
},
"data": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
"responses": {
"200": {
"description": "Contact updated",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Contact"
}
}
}
}
}
}
}
},
"delete": {
"tags": ["Contacts"],
"summary": "Delete contact",
"description": "Permanently delete a contact",
"operationId": "deleteContact",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Contact deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
},
"/templates": {
"get": {
"tags": ["Templates"],
"summary": "List templates",
"description": "Get a paginated list of email templates",
"operationId": "listTemplates",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"$ref": "#/components/parameters/Limit"
},
{
"$ref": "#/components/parameters/Cursor"
},
{
"name": "type",
"in": "query",
"schema": {
"type": "string",
"enum": ["TRANSACTIONAL", "MARKETING"]
}
},
{
"name": "search",
"in": "query",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "List of templates",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Template"
}
}
}
}
}
}
}
}
}
}
},
"post": {
"tags": ["Templates"],
"summary": "Create template",
"description": "Create a new email template",
"operationId": "createTemplate",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["name", "subject", "body", "type"],
"properties": {
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body": {
"type": "string"
},
"type": {
"type": "string",
"enum": ["TRANSACTIONAL", "MARKETING"]
}
}
}
}
}
},
"responses": {
"200": {
"description": "Template created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Template"
}
}
}
}
}
}
}
}
},
"/campaigns": {
"get": {
"tags": ["Campaigns"],
"summary": "List campaigns",
"description": "Get a paginated list of email campaigns",
"operationId": "listCampaigns",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"$ref": "#/components/parameters/Limit"
},
{
"$ref": "#/components/parameters/Cursor"
},
{
"name": "status",
"in": "query",
"schema": {
"type": "string",
"enum": ["DRAFT", "SCHEDULED", "SENDING", "SENT"]
}
}
],
"responses": {
"200": {
"description": "List of campaigns",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Campaign"
}
}
}
}
}
}
}
}
}
}
},
"post": {
"tags": ["Campaigns"],
"summary": "Create campaign",
"description": "Create a new email campaign",
"operationId": "createCampaign",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["name", "subject", "body", "from", "audienceType"],
"properties": {
"name": {
"type": "string",
"description": "Campaign name"
},
"description": {
"type": "string",
"description": "Campaign description"
},
"subject": {
"type": "string",
"description": "Email subject line"
},
"body": {
"type": "string",
"description": "HTML email body"
},
"from": {
"type": "string",
"format": "email",
"description": "Sender email address (must be from verified domain)"
},
"fromName": {
"type": "string",
"description": "Sender name"
},
"replyTo": {
"type": "string",
"format": "email",
"description": "Reply-to email address"
},
"audienceType": {
"type": "string",
"enum": ["ALL", "SEGMENT", "FILTERED"],
"description": "Target audience type"
},
"segmentId": {
"type": "string",
"description": "Segment ID (required if audienceType is SEGMENT)"
},
"audienceFilter": {
"type": "object",
"description": "Filter conditions (required if audienceType is FILTERED)"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Campaign created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Campaign"
}
}
}
}
}
}
}
}
},
"/campaigns/{id}/send": {
"post": {
"tags": ["Campaigns"],
"summary": "Send or schedule campaign",
"description": "Send a campaign immediately or schedule for future delivery",
"operationId": "sendCampaign",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"scheduledFor": {
"type": "string",
"format": "date-time",
"nullable": true,
"description": "ISO 8601 timestamp for when to send the campaign. Omit or set to null for immediate send."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Campaign scheduled/sending"
}
}
}
},
"/segments": {
"get": {
"tags": ["Segments"],
"summary": "List segments",
"description": "Get all audience segments",
"operationId": "listSegments",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
}
],
"responses": {
"200": {
"description": "List of segments",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Segment"
}
}
}
}
}
}
}
}
},
"post": {
"tags": ["Segments"],
"summary": "Create segment",
"description": "Create a new audience segment",
"operationId": "createSegment",
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["name", "filters"],
"properties": {
"name": {
"type": "string"
},
"filters": {
"type": "object",
"description": "Filter conditions"
},
"trackMembership": {
"type": "boolean",
"default": false
}
}
},
"example": {
"name": "Premium Users",
"filters": {
"operator": "AND",
"conditions": [
{
"field": "data.plan",
"operator": "equals",
"value": "premium"
}
]
},
"trackMembership": true
}
}
}
},
"responses": {
"200": {
"description": "Segment created",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"data": {
"$ref": "#/components/schemas/Segment"
}
}
}
}
}
}
}
}
}
},
"tags": [
{
"name": "Public API",
"description": "Public API endpoints for sending emails and tracking events"
},
{
"name": "Contacts",
"description": "Contact management operations"
},
{
"name": "Templates",
"description": "Email template management"
},
{
"name": "Campaigns",
"description": "Email campaign management"
},
{
"name": "Segments",
"description": "Audience segmentation"
}
]
}