#Survey flows
GET /survey-flows
List the organization's survey flows, the automations that email customers for a review after an order. Supports search, filtering and cursor pagination.
Requires the surveys:read permission.
Query Parameters
limitnumberThe number of records to return.
cursorstringA pagination cursor. Fetch the next page by passing the nextCursor value from the previous response.
sortname | -name | createdAt | -createdAtThe sort order. Prefix a field with - to sort descending. Defaults to name.
searchstringA free-text search term, matched case-insensitively against the record's most identifying fields. Combined with filter using AND.
filterstringA JSON-encoded filter document, for example {"createdAt":{"$gte":"2025-01-01T00:00:00Z"}}. Filterable fields: id, name, isActive, triggerEvent, createdAt. See Filtering for the syntax.
curl \
"https://api.cascade.dev/survey-flows" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getSurveyFlows } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getSurveyFlows()require "net/http"
uri = URI("https://api.cascade.dev/survey-flows")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/survey-flows",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": ["..."],
"metadata": "...",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
],
"nextCursor": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the survey flow."
},
"name": {
"type": "string",
"description": "The flow's display name."
},
"isActive": {
"type": "boolean",
"description": "Whether the flow runs. An inactive flow ignores its trigger event."
},
"triggerEvent": {
"type": "string",
"enum": ["orderCreated", "orderShipped", "orderDelivered"],
"description": "The order event that starts the flow."
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A JSON filter document the order has to match for the flow to run, or null to run for every order. Can match on `order`, `customer`, `site`, `products` and `variants`."
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the step."
},
"type": {
"type": "string",
"enum": ["sendEmail", "sendWebhook"],
"description": "What the step does when it runs."
},
"position": {
"type": "number",
"description": "The step's zero-based place in the flow. Steps run in this order."
},
"emailTemplateId": {
"description": "For `sendEmail` steps, the ID of the template to send.",
"type": "string"
},
"url": {
"description": "For `sendWebhook` steps, the URL to POST to.",
"type": "string"
},
"waitSeconds": {
"type": "number",
"description": "How long to wait after the previous step before running this one, in seconds."
}
},
"required": ["id", "type", "position", "waitSeconds"],
"additionalProperties": false
},
"description": "The flow's steps, in the order they run."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
},
"description": "Free-form string key/value pairs for your own data. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was last changed."
}
},
"required": [
"id",
"name",
"isActive",
"triggerEvent",
"condition",
"steps",
"metadata",
"createdAt",
"updatedAt"
],
"additionalProperties": false
},
"description": "The page of records, in the requested sort order."
},
"nextCursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Pass this back as `cursor` to fetch the next page. Null once the last page has been returned."
}
},
"required": ["data", "nextCursor"],
"additionalProperties": false
}POST /survey-flows
Create a survey flow. It starts running against new orders as soon as it is active. Triggers the surveyFlow.created webhook.
Requires the surveys:write permission.
Body Parameters
dataobjectrequiredThe flow to create.
curl \
-X POST \
"https://api.cascade.dev/survey-flows" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}'import { client } from "@cascade-commerce/api/admin/client"
import { postSurveyFlows } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postSurveyFlows({
body: {
data: {
name: "string",
isActive: true,
triggerEvent: "orderCreated",
condition: "string",
steps: [
{
id: "...",
type: "...",
emailTemplateId: "...",
waitSeconds: "...",
},
],
metadata: "...",
},
},
})require "net/http"
uri = URI("https://api.cascade.dev/survey-flows")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}"""
req = Request(
"https://api.cascade.dev/survey-flows",
data=body.encode(),
headers={
"Authorization": "Bearer sk_YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
)
with urlopen(req) as res:
print(json.load(res)){
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "sendEmail",
"position": 0,
"emailTemplateId": "string",
"url": "string",
"waitSeconds": 0
}
],
"metadata": "...",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the survey flow."
},
"name": {
"type": "string",
"description": "The flow's display name."
},
"isActive": {
"type": "boolean",
"description": "Whether the flow runs. An inactive flow ignores its trigger event."
},
"triggerEvent": {
"type": "string",
"enum": ["orderCreated", "orderShipped", "orderDelivered"],
"description": "The order event that starts the flow."
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A JSON filter document the order has to match for the flow to run, or null to run for every order. Can match on `order`, `customer`, `site`, `products` and `variants`."
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the step."
},
"type": {
"type": "string",
"enum": ["sendEmail", "sendWebhook"],
"description": "What the step does when it runs."
},
"position": {
"type": "number",
"description": "The step's zero-based place in the flow. Steps run in this order."
},
"emailTemplateId": {
"description": "For `sendEmail` steps, the ID of the template to send.",
"type": "string"
},
"url": {
"description": "For `sendWebhook` steps, the URL to POST to.",
"type": "string"
},
"waitSeconds": {
"type": "number",
"description": "How long to wait after the previous step before running this one, in seconds."
}
},
"required": ["id", "type", "position", "waitSeconds"],
"additionalProperties": false
},
"description": "The flow's steps, in the order they run."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
},
"description": "Free-form string key/value pairs for your own data. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was last changed."
}
},
"required": [
"id",
"name",
"isActive",
"triggerEvent",
"condition",
"steps",
"metadata",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The new survey flow."
}GET /survey-flows/{id}
Get a single survey flow by ID, including its steps.
Requires the surveys:read permission.
Path Parameters
idstring (uuid)requiredThe ID of the survey flow.
curl \
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getSurveyFlowsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getSurveyFlowsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
})require "net/http"
uri = URI("https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "sendEmail",
"position": 0,
"emailTemplateId": "string",
"url": "string",
"waitSeconds": 0
}
],
"metadata": "...",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the survey flow."
},
"name": {
"type": "string",
"description": "The flow's display name."
},
"isActive": {
"type": "boolean",
"description": "Whether the flow runs. An inactive flow ignores its trigger event."
},
"triggerEvent": {
"type": "string",
"enum": ["orderCreated", "orderShipped", "orderDelivered"],
"description": "The order event that starts the flow."
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A JSON filter document the order has to match for the flow to run, or null to run for every order. Can match on `order`, `customer`, `site`, `products` and `variants`."
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the step."
},
"type": {
"type": "string",
"enum": ["sendEmail", "sendWebhook"],
"description": "What the step does when it runs."
},
"position": {
"type": "number",
"description": "The step's zero-based place in the flow. Steps run in this order."
},
"emailTemplateId": {
"description": "For `sendEmail` steps, the ID of the template to send.",
"type": "string"
},
"url": {
"description": "For `sendWebhook` steps, the URL to POST to.",
"type": "string"
},
"waitSeconds": {
"type": "number",
"description": "How long to wait after the previous step before running this one, in seconds."
}
},
"required": ["id", "type", "position", "waitSeconds"],
"additionalProperties": false
},
"description": "The flow's steps, in the order they run."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
},
"description": "Free-form string key/value pairs for your own data. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was last changed."
}
},
"required": [
"id",
"name",
"isActive",
"triggerEvent",
"condition",
"steps",
"metadata",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The requested survey flow."
}PUT /survey-flows/{id}
Update a survey flow. Sending steps replaces the whole list, and surveys already in flight keep running against the old steps. Triggers the surveyFlow.updated webhook.
Requires the surveys:write permission.
Path Parameters
idstring (uuid)requiredThe ID of the survey flow to update.
Body Parameters
dataobjectrequiredThe fields to update.
curl \
-X PUT \
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}'import { client } from "@cascade-commerce/api/admin/client"
import { putSurveyFlowsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await putSurveyFlowsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
body: {
data: {
name: "string",
isActive: true,
triggerEvent: "orderCreated",
condition: "string",
steps: [
{
id: "...",
type: "...",
emailTemplateId: "...",
waitSeconds: "...",
},
],
metadata: "...",
},
},
})require "net/http"
uri = URI("https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000")
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"data": {
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "...",
"type": "...",
"emailTemplateId": "...",
"waitSeconds": "..."
}
],
"metadata": "..."
}
}"""
req = Request(
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000",
data=body.encode(),
method="PUT",
headers={
"Authorization": "Bearer sk_YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
)
with urlopen(req) as res:
print(json.load(res)){
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "sendEmail",
"position": 0,
"emailTemplateId": "string",
"url": "string",
"waitSeconds": 0
}
],
"metadata": "...",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the survey flow."
},
"name": {
"type": "string",
"description": "The flow's display name."
},
"isActive": {
"type": "boolean",
"description": "Whether the flow runs. An inactive flow ignores its trigger event."
},
"triggerEvent": {
"type": "string",
"enum": ["orderCreated", "orderShipped", "orderDelivered"],
"description": "The order event that starts the flow."
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A JSON filter document the order has to match for the flow to run, or null to run for every order. Can match on `order`, `customer`, `site`, `products` and `variants`."
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the step."
},
"type": {
"type": "string",
"enum": ["sendEmail", "sendWebhook"],
"description": "What the step does when it runs."
},
"position": {
"type": "number",
"description": "The step's zero-based place in the flow. Steps run in this order."
},
"emailTemplateId": {
"description": "For `sendEmail` steps, the ID of the template to send.",
"type": "string"
},
"url": {
"description": "For `sendWebhook` steps, the URL to POST to.",
"type": "string"
},
"waitSeconds": {
"type": "number",
"description": "How long to wait after the previous step before running this one, in seconds."
}
},
"required": ["id", "type", "position", "waitSeconds"],
"additionalProperties": false
},
"description": "The flow's steps, in the order they run."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
},
"description": "Free-form string key/value pairs for your own data. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was last changed."
}
},
"required": [
"id",
"name",
"isActive",
"triggerEvent",
"condition",
"steps",
"metadata",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The updated survey flow."
}DELETE /survey-flows/{id}
Delete a survey flow and its steps. To stop it temporarily, set isActive to false instead. Triggers the surveyFlow.deleted webhook.
Requires the surveys:write permission.
Path Parameters
idstring (uuid)requiredThe ID of the survey flow to delete.
curl \
-X DELETE \
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { deleteSurveyFlowsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await deleteSurveyFlowsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
})require "net/http"
uri = URI("https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/survey-flows/550e8400-e29b-41d4-a716-446655440000",
method="DELETE",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"isActive": true,
"triggerEvent": "orderCreated",
"condition": "string",
"steps": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "sendEmail",
"position": 0,
"emailTemplateId": "string",
"url": "string",
"waitSeconds": 0
}
],
"metadata": "...",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the survey flow."
},
"name": {
"type": "string",
"description": "The flow's display name."
},
"isActive": {
"type": "boolean",
"description": "Whether the flow runs. An inactive flow ignores its trigger event."
},
"triggerEvent": {
"type": "string",
"enum": ["orderCreated", "orderShipped", "orderDelivered"],
"description": "The order event that starts the flow."
},
"condition": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A JSON filter document the order has to match for the flow to run, or null to run for every order. Can match on `order`, `customer`, `site`, `products` and `variants`."
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Unique identifier for the step."
},
"type": {
"type": "string",
"enum": ["sendEmail", "sendWebhook"],
"description": "What the step does when it runs."
},
"position": {
"type": "number",
"description": "The step's zero-based place in the flow. Steps run in this order."
},
"emailTemplateId": {
"description": "For `sendEmail` steps, the ID of the template to send.",
"type": "string"
},
"url": {
"description": "For `sendWebhook` steps, the URL to POST to.",
"type": "string"
},
"waitSeconds": {
"type": "number",
"description": "How long to wait after the previous step before running this one, in seconds."
}
},
"required": ["id", "type", "position", "waitSeconds"],
"additionalProperties": false
},
"description": "The flow's steps, in the order they run."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
},
"description": "Free-form string key/value pairs for your own data. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was created."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the flow was last changed."
}
},
"required": [
"id",
"name",
"isActive",
"triggerEvent",
"condition",
"steps",
"metadata",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The deleted survey flow."
}