#Integrations
GET /integrations
List the organization's connected storefront integrations, newest first. Access tokens are never returned.
Requires the settings: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.
sortcreatedAt | -createdAtThe sort order. Prefix a field with - to sort descending. Defaults to -createdAt.
filterstringA JSON-encoded filter document, for example {"createdAt":{"$gte":"2025-01-01T00:00:00Z"}}. Filterable fields: id, type, createdAt. See Filtering for the syntax.
curl \
"https://api.cascade.dev/integrations" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getIntegrations } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getIntegrations()require "net/http"
uri = URI("https://api.cascade.dev/integrations")
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/integrations",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "shopify",
"publicData": "...",
"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 integration."
},
"type": {
"type": "string",
"enum": ["shopify"],
"description": "Which platform the integration connects to."
},
"publicData": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Connection details safe to show, such as the store domain and sync settings. Credentials are never included."
},
"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 integration was connected."
},
"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 integration was last changed."
}
},
"required": ["id", "type", "publicData", "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
}GET /integrations/{id}
Get a single integration by ID.
Requires the settings:read permission.
Path Parameters
idstring (uuid)requiredThe ID of the integration.
curl \
"https://api.cascade.dev/integrations/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getIntegrationsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getIntegrationsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
})require "net/http"
uri = URI("https://api.cascade.dev/integrations/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/integrations/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",
"type": "shopify",
"publicData": "...",
"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 integration."
},
"type": {
"type": "string",
"enum": ["shopify"],
"description": "Which platform the integration connects to."
},
"publicData": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Connection details safe to show, such as the store domain and sync settings. Credentials are never included."
},
"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 integration was connected."
},
"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 integration was last changed."
}
},
"required": ["id", "type", "publicData", "createdAt", "updatedAt"],
"additionalProperties": false,
"description": "The requested integration."
}PATCH /integrations/{id}
Update how a connected integration behaves in Cascade. Only the settings you send are changed, and the rest are left alone. These are Cascade's own settings, not the store's.
Requires the settings:write permission.
Path Parameters
idstring (uuid)requiredThe ID of the integration.
Body Parameters
settingsobjectThe sync settings to change. Anything you leave out keeps its current value.
curl \
-X PATCH \
"https://api.cascade.dev/integrations/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"onProductDelete": "delete",
"onCustomerDelete": "delete",
"onOrderDelete": "delete",
"earnOn": "orderCreated",
"earnOnBackfill": true,
"metafieldMappings": [
{
"resource": "...",
"namespace": "...",
"key": "...",
"metadataKey": "..."
}
]
}
}'import { client } from "@cascade-commerce/api/admin/client"
import { patchIntegrationsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await patchIntegrationsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
body: {
settings: {
onProductDelete: "delete",
onCustomerDelete: "delete",
onOrderDelete: "delete",
earnOn: "orderCreated",
earnOnBackfill: true,
metafieldMappings: [
{
resource: "...",
namespace: "...",
key: "...",
metadataKey: "...",
},
],
},
},
})require "net/http"
uri = URI("https://api.cascade.dev/integrations/550e8400-e29b-41d4-a716-446655440000")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"settings": {
"onProductDelete": "delete",
"onCustomerDelete": "delete",
"onOrderDelete": "delete",
"earnOn": "orderCreated",
"earnOnBackfill": true,
"metafieldMappings": [
{
"resource": "...",
"namespace": "...",
"key": "...",
"metadataKey": "..."
}
]
}
}
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 = """{
"settings": {
"onProductDelete": "delete",
"onCustomerDelete": "delete",
"onOrderDelete": "delete",
"earnOn": "orderCreated",
"earnOnBackfill": true,
"metafieldMappings": [
{
"resource": "...",
"namespace": "...",
"key": "...",
"metadataKey": "..."
}
]
}
}"""
req = Request(
"https://api.cascade.dev/integrations/550e8400-e29b-41d4-a716-446655440000",
data=body.encode(),
method="PATCH",
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",
"type": "shopify",
"publicData": "...",
"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 integration."
},
"type": {
"type": "string",
"enum": ["shopify"],
"description": "Which platform the integration connects to."
},
"publicData": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Connection details safe to show, such as the store domain and sync settings. Credentials are never included."
},
"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 integration was connected."
},
"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 integration was last changed."
}
},
"required": ["id", "type", "publicData", "createdAt", "updatedAt"],
"additionalProperties": false,
"description": "The updated integration."
}DELETE /integrations/{id}
Disconnect an integration. Syncing stops and the stored access token is discarded. Records already synced into Cascade are kept.
Requires the settings:write permission.
Path Parameters
idstring (uuid)requiredThe ID of the integration to disconnect.
curl \
-X DELETE \
"https://api.cascade.dev/integrations/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { deleteIntegrationsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await deleteIntegrationsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
})require "net/http"
uri = URI("https://api.cascade.dev/integrations/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/integrations/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",
"type": "shopify",
"publicData": "...",
"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 integration."
},
"type": {
"type": "string",
"enum": ["shopify"],
"description": "Which platform the integration connects to."
},
"publicData": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Connection details safe to show, such as the store domain and sync settings. Credentials are never included."
},
"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 integration was connected."
},
"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 integration was last changed."
}
},
"required": ["id", "type", "publicData", "createdAt", "updatedAt"],
"additionalProperties": false,
"description": "The disconnected integration."
}GET /integrations/shopify/connect-context
Check whether a Shopify store can be connected to this organization, and say why not if it cannot. The connect screen calls this so it never offers a button that would fail after the OAuth round trip.
Requires the settings:read permission.
Query Parameters
shopstringrequiredThe myshopify.com domain of the store being connected
curl \
"https://api.cascade.dev/integrations/shopify/connect-context" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getIntegrationsShopifyConnectContext } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getIntegrationsShopifyConnectContext({
query: { shop: "string" },
})require "net/http"
uri = URI("https://api.cascade.dev/integrations/shopify/connect-context")
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/integrations/shopify/connect-context",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"shop": "string",
"organization": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string"
},
"siteCount": 0,
"siteLimit": 0,
"blockedReason": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"shop": {
"type": "string",
"description": "The myshopify.com domain that was checked."
},
"organization": {
"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 organization."
},
"name": {
"type": "string",
"description": "The organization's display name."
}
},
"required": ["id", "name"],
"additionalProperties": false,
"description": "The organization the store would be connected to."
},
"siteCount": {
"type": "number",
"description": "How many sites the organization already has."
},
"siteLimit": {
"type": "number",
"description": "How many sites its plan allows."
},
"blockedReason": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Why the store cannot be connected, ready to show to the merchant. Null when the connection can go ahead."
}
},
"required": ["shop", "organization", "siteCount", "siteLimit", "blockedReason"],
"additionalProperties": false,
"description": "What connecting this store would mean."
}POST /integrations/shopify/grant
Authorize the Shopify connector to connect a store to the signed-in user's organization
Requires the settings:write permission.
Body Parameters
shopstringrequiredThe myshopify.com domain of the store being connected
statestringrequiredThe connector's one-time state nonce
curl \
-X POST \
"https://api.cascade.dev/integrations/shopify/grant" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"shop": "string",
"state": "string"
}'import { client } from "@cascade-commerce/api/admin/client"
import { postIntegrationsShopifyGrant } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postIntegrationsShopifyGrant({
body: {
shop: "string",
state: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/integrations/shopify/grant")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"shop": "string",
"state": "string"
}
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 = """{
"shop": "string",
"state": "string"
}"""
req = Request(
"https://api.cascade.dev/integrations/shopify/grant",
data=body.encode(),
headers={
"Authorization": "Bearer sk_YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
)
with urlopen(req) as res:
print(json.load(res)){
"grant": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"grant": {
"type": "string",
"description": "A short-lived signed grant. Hand it back to the connector, which carries it through Shopify's OAuth round trip."
}
},
"required": ["grant"],
"additionalProperties": false,
"description": "The signed authorization to connect the store."
}