Messaging API
REST endpoints for messaging in SKUFlow: 8 operations with parameters, request and response fields, permissions and curl examples.
Base URL: https://app.skuflow.ai/api. Every call needs Authorization: Bearer skf_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.
| Operation | Endpoint | Risk |
|---|---|---|
| Get messaging settings | GET /organizations/{organizationId}/messaging/settings | read |
| Change messaging settings | PATCH /organizations/{organizationId}/messaging/settings | write |
| List the email and SMS providers | GET /organizations/{organizationId}/messaging/channels | read |
| Connect an email or SMS provider | PATCH /organizations/{organizationId}/messaging/channels/{channel} | sensitive |
| Disconnect a provider (back to test mode) | DELETE /organizations/{organizationId}/messaging/channels/{channel} | sensitive |
| Send a test message | POST /organizations/{organizationId}/messaging/channels/{channel}/test | sensitive |
| Simulate a customer's text reply (test mode) | POST /organizations/{organizationId}/messaging/simulate-reply | write |
| Run the automations now | POST /organizations/{organizationId}/messaging/run | sensitive |
Get messaging settings
GET /organizations/{organizationId}/messaging/settings
Quiet hours (in the organization's timezone; default 21:00–08:00), the cap on automated messages per customer per day, sender name, reply-to, business phone and review link. Read-only.
| Permission | engagement.read (Owner, Admin, Staff) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | messaging_settings (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/settings" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
quietHoursEnabled | boolean | |
quietHoursStart | string | |
quietHoursEnd | string | |
maxPerCustomerPerDay | integer | |
senderName | string or null | |
replyTo | string or null | |
businessPhone | string or null | |
reviewUrl | string or null | |
emailBrandColor | string or null | Email branding: the accent colour (#rrggbb); null = SKUFlow blue. |
emailHeaderText | string or null | Email branding: the line under the logo. |
emailFooterText | string or null | Email branding: the business's footer text. |
timezone | string | The organization's timezone: quiet hours are counted in it. |
updatedAt | string or null | ISO 8601 time (UTC). |
Change messaging settings
PATCH /organizations/{organizationId}/messaging/settings
Quiet hours, the daily cap per customer, sender name, reply-to, business phone and review link. Only the fields sent change.
| Permission | engagement.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | messaging_updateSettings (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
quietHoursEnabled | boolean | No | |
quietHoursStart | string | No | Start of quiet hours, HH:MM in the org timezone. |
quietHoursEnd | string | No | End of quiet hours, HH:MM in the org timezone. |
maxPerCustomerPerDay | integer | No | Automated messages per customer per day; 0 = no cap. 0–50. |
senderName | string or null | No | Up to 100 characters. |
replyTo | empty string or string (email) or null | No | |
businessPhone | string or null | No | Up to 32 characters. |
reviewUrl | empty string or string (uri) or null | No | Where review requests point, e.g. your Google review link. |
emailBrandColor | empty string or string or null | No | Email branding: the accent colour of the header bar and buttons (#rrggbb). |
emailHeaderText | string or null | No | Email branding: a line under the logo, e.g. "Custom printing since 1998". Up to 120 characters. |
emailFooterText | string or null | No | Email branding: the business's own footer text (website, hours, license number). Up to 500 characters. |
Example
curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/settings" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"quietHoursEnabled":true,"quietHoursStart":"09:00","quietHoursEnd":"09:00"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
quietHoursEnabled | boolean | |
quietHoursStart | string | |
quietHoursEnd | string | |
maxPerCustomerPerDay | integer | |
senderName | string or null | |
replyTo | string or null | |
businessPhone | string or null | |
reviewUrl | string or null | |
emailBrandColor | string or null | Email branding: the accent colour (#rrggbb); null = SKUFlow blue. |
emailHeaderText | string or null | Email branding: the line under the logo. |
emailFooterText | string or null | Email branding: the business's footer text. |
timezone | string | The organization's timezone: quiet hours are counted in it. |
updatedAt | string or null | ISO 8601 time (UTC). |
List the email and SMS providers
GET /organizations/{organizationId}/messaging/channels
The provider of each channel: test mode (log only, the default) or the connected provider with its sender, the last four characters of its credential, its webhook URLs (inbound texts, delivery status, bounces) and the last test. Never returns credentials. Read-only.
| Permission | channels.manage (Owner, Admin) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | messaging_channels (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/channels" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
channels | array of object | |
channels[].channel | enum | One of EMAIL, SMS. |
channels[].providerKey | string | test (log only) | skuflow_email (SKUFlow email, the default for new businesses) | resend | postmark | sendgrid | mailgun | ses | skuflow (SKUFlow texting) | twilio |
channels[].testMode | boolean | |
channels[].settings | object | Sender and options; never credentials. |
channels[].secretHint | string or null | Last four characters of the main credential. |
channels[].webhookUrls | object | |
channels[].webhookUrls.inbound | string or null | |
channels[].webhookUrls.status | string or null | |
channels[].webhookUrls.events | string or null | |
channels[].lastTestedAt | string or null | ISO 8601 time (UTC). |
channels[].lastTestError | string or null | |
channels[].updatedAt | string or null | ISO 8601 time (UTC). |
providers | array of object | |
providers[].key | string | |
providers[].channel | string | |
providers[].label | string |
Connect an email or SMS provider
PATCH /organizations/{organizationId}/messaging/channels/{channel}
Sends data out: sets the channel's provider: test (log only), or resend / postmark / sendgrid / mailgun / ses (EMAIL) or twilio (SMS) with its sender and credentials. Credentials are encrypted at rest and never returned; leave a credential blank to keep the stored one. From then on messages really go out through it.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | messaging_setChannel (toolset settings) |
| Approval | Waits for your approval in SKUFlow when called with an API key or a connected app: the first call answers 428 APPROVAL_REQUIRED; once you approve it, repeat the call with the X-SKUFlow-Approval header. See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel | path | enum | Yes | One of EMAIL, SMS. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
providerKey | enum | Yes | One of test, resend, postmark, sendgrid, mailgun, ses, twilio. |
fromAddress | string | No | Up to 254 characters. |
fromName | string | No | Up to 100 characters. |
fromNumber | string | No | Twilio: the sending number (+E.164). Up to 32 characters. |
messagingServiceSid | string | No | Up to 64 characters. |
region | string | No | SES region, or Mailgun us / eu. Up to 32 characters. |
domain | string | No | Mailgun sending domain. Up to 253 characters. |
messageStream | string | No | Postmark message stream. Up to 100 characters. |
apiKey | string | No | Credential (write-only). Up to 500 characters. |
serverToken | string | No | Credential (write-only). Up to 500 characters. |
accessKeyId | string | No | Credential (write-only). Up to 200 characters. |
secretAccessKey | string | No | Credential (write-only). Up to 500 characters. |
accountSid | string | No | Credential (write-only). Up to 100 characters. |
authToken | string | No | Credential (write-only). Up to 200 characters. |
webhookSigningSecret | string | No | Bounce webhook signing secret (write-only). Up to 500 characters. |
Example
curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/channels/{channel}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"providerKey":"test"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
channel | enum | One of EMAIL, SMS. |
providerKey | string | test (log only) | skuflow_email (SKUFlow email, the default for new businesses) | resend | postmark | sendgrid | mailgun | ses | skuflow (SKUFlow texting) | twilio |
testMode | boolean | |
settings | object | Sender and options; never credentials. |
secretHint | string or null | Last four characters of the main credential. |
webhookUrls | object | |
webhookUrls.inbound | string or null | |
webhookUrls.status | string or null | |
webhookUrls.events | string or null | |
lastTestedAt | string or null | ISO 8601 time (UTC). |
lastTestError | string or null | |
updatedAt | string or null | ISO 8601 time (UTC). |
Disconnect a provider (back to test mode)
DELETE /organizations/{organizationId}/messaging/channels/{channel}
Destructive: deletes the channel's provider and its stored credentials; messages are logged in test mode (SENT_TEST) again and nothing is sent.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | messaging_removeChannel (toolset settings) |
| Approval | Over MCP, this tool always waits for your approval in SKUFlow. See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel | path | enum | Yes | One of EMAIL, SMS. |
Example
curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/channels/{channel}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
channel | enum | One of EMAIL, SMS. |
providerKey | string | test (log only) | skuflow_email (SKUFlow email, the default for new businesses) | resend | postmark | sendgrid | mailgun | ses | skuflow (SKUFlow texting) | twilio |
testMode | boolean | |
settings | object | Sender and options; never credentials. |
secretHint | string or null | Last four characters of the main credential. |
webhookUrls | object | |
webhookUrls.inbound | string or null | |
webhookUrls.status | string or null | |
webhookUrls.events | string or null | |
lastTestedAt | string or null | ISO 8601 time (UTC). |
lastTestError | string or null | |
updatedAt | string or null | ISO 8601 time (UTC). |
Send a test message
POST /organizations/{organizationId}/messaging/channels/{channel}/test
Sends a message: a short test email or text to the given address through the channel's provider (in test mode it is only logged, SENT_TEST). The outcome is recorded on the provider and in the message log.
| Permission | channels.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | messaging_testSend (toolset settings) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel | path | enum | Yes | One of EMAIL, SMS. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Email address or phone number. Up to 254 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/channels/{channel}/test" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"2026-11-03"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | |
direction | enum | One of OUTBOUND, INBOUND. |
source | enum | System: a message the customer asked for themselves (a portal sign-in code; its code is scrubbed once sent). One of AUTOMATION, MANUAL, TEST, INBOUND, CAMPAIGN, SYSTEM. |
channel | enum | One of EMAIL, SMS. |
purpose | enum | One of TRANSACTIONAL, MARKETING. |
status | enum | One of QUEUED, DEFERRED, SENDING, SENT, SENT_TEST, DELIVERED, FAILED, BOUNCED, SKIPPED, CANCELLED, RECEIVED. |
statusReason | string or null | |
provider | string or null | |
toAddress | string or null | |
fromAddress | string or null | |
subject | string or null | |
preview | string | The first 160 characters of the body. |
customerId | string or null | |
customerName | string or null | |
ruleId | string or null | |
ruleName | string or null | |
campaignId | string or null | The marketing campaign it belongs to (source CAMPAIGN). |
openedAt | string or null | First open the email provider reported. |
clickedAt | string or null | First click the email provider reported. |
subjectType | string or null | |
subjectId | string or null | |
scheduledFor | string | ISO 8601 time (UTC). |
sentAt | string or null | ISO 8601 time (UTC). |
createdAt | string | ISO 8601 time (UTC). |
Simulate a customer's text reply (test mode)
POST /organizations/{organizationId}/messaging/simulate-reply
Test mode only (no SMS provider connected): processes a text as if the customer sent it from from, exactly like a signed Twilio webhook: STOP / START / HELP change consent, the reply is logged as an inbound message and message.replied ends cadences. 400 with a real provider (replies come from its webhook).
| Permission | channels.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | messaging_simulateReply (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | The customer's phone number. Up to 32 characters. |
body | string | Yes | Up to 1600 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/simulate-reply" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-11-03","body":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
messageId | string | |
customerId | string or null | |
keyword | enum or null | One of STOP, START, HELP. |
reply | string or null |
Run the automations now
POST /organizations/{organizationId}/messaging/run
Customer-facing: runs this organization's engine once without waiting for the worker: arms and fires due RELATIVE timers (reminders), runs due scheduled rules, advances cadences and sends due messages. The outbox (events) is consumed for every organization in order, as the worker does. now is for tests only (refused in production).
| Permission | engagement.manage (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | messaging_runNow (toolset settings) |
| Approval | Over MCP, this tool always waits for your approval in SKUFlow. See Approvals. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
now | string (date-time) | No | Tests only: run as of this moment (ISO 8601). Refused when the server runs with NODE_ENV=production. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/messaging/run" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"now":"2026-11-03T15:00:00Z"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
ranAt | string | |
events | integer | |
timers | object | |
timers.armed | integer | |
timers.fired | integer | |
timers.cancelled | integer | |
timers.skipped | integer | |
cadenceSteps | integer | |
messages | object | |
messages.attempted | integer | |
messages.sent | integer | |
messages.test | integer | |
messages.failed | integer | |
messages.skipped | integer | |
messages.retrying | integer |
Customer messaging API
REST endpoints for customer messaging in SKUFlow: 2 operations with parameters, request and response fields, permissions and curl examples.
Skuflow email API
REST endpoints for skuflow email in SKUFlow: 7 operations with parameters, request and response fields, permissions and curl examples.