#Export jobs
GET /export-jobs
List the organization's CSV export jobs, newest first. A completed job carries a signed fileUrl to download.
Requires the exports: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, status, createdAt. See Filtering for the syntax.
curl \
"https://api.cascade.dev/export-jobs" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getExportJobs } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getExportJobs()require "net/http"
uri = URI("https://api.cascade.dev/export-jobs")
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/export-jobs",
headers={"Authorization": "Bearer sk_YOUR_SECRET_KEY"},
)
with urlopen(req) as res:
print(json.load(res)){
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "550e8400-e29b-41d4-a716-446655440000",
"fileUrl": "string",
"type": "customers",
"status": "pending",
"totalCount": 0,
"filter": "...",
"search": "string",
"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 export job."
},
"userId": {
"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": "The user who started the export."
},
"fileUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A signed URL to download the finished CSV. Null until the export completes."
},
"type": {
"type": "string",
"enum": [
"customers",
"products",
"orders",
"surveys",
"reviews",
"wishlists",
"loyalty-activity",
"loyalty-members",
"referrals"
],
"description": "Which records the export covers."
},
"status": {
"type": "string",
"enum": ["pending", "processing", "completed", "failed"],
"description": "Where the export has got to. Failed means the export gave up and wrote no file."
},
"totalCount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"description": "How many rows were written, once the export finishes."
},
"filter": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
{
"type": "null"
}
],
"description": "The filter document the export was narrowed to. Null when the export covers every record of its type."
},
"search": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The free-text search the export was narrowed to, if there was one."
},
"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 export was started."
},
"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 export last made progress."
}
},
"required": [
"id",
"userId",
"fileUrl",
"type",
"status",
"totalCount",
"filter",
"search",
"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 /export-jobs
Queue a CSV export of records of one type, optionally narrowed by a filter. It runs in the background, so poll the job until it completes and then download fileUrl. Only session-authenticated requests can start one, since an export is attributed to a user.
Requires the exports:write permission.
Costs 10 rate limit tokens instead of the usual one. See Rate limits.
Body Parameters
typecustomers | products | orders | surveys | reviews | wishlists | loyalty-activity | loyalty-members | referralsrequiredWhich records to export.
filterstringA JSON-encoded filter document, in the same shape the matching list endpoint takes. Only the records it matches are exported. Omit to export every record of this type.
searchstringA free-text search term, matched the same way the matching list endpoint matches it. Combined with filter using AND.
curl \
-X POST \
"https://api.cascade.dev/export-jobs" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "customers",
"filter": "string",
"search": "string"
}'import { client } from "@cascade-commerce/api/admin/client"
import { postExportJobs } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postExportJobs({
body: {
type: "customers",
filter: "string",
search: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/export-jobs")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer sk_YOUR_SECRET_KEY"
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"type": "customers",
"filter": "string",
"search": "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 = """{
"type": "customers",
"filter": "string",
"search": "string"
}"""
req = Request(
"https://api.cascade.dev/export-jobs",
data=body.encode(),
headers={
"Authorization": "Bearer sk_YOUR_SECRET_KEY",
"Content-Type": "application/json",
},
)
with urlopen(req) as res:
print(json.load(res)){
"exportJobId": "550e8400-e29b-41d4-a716-446655440000"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"exportJobId": {
"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": "The ID of the queued export job."
}
},
"required": ["exportJobId"],
"additionalProperties": false,
"description": "A handle you can poll for progress."
}GET /export-jobs/{id}
Get a single export job by ID. Once its status is completed, fileUrl is a signed link to the CSV.
Requires the exports:read permission.
Path Parameters
idstring (uuid)requiredThe ID of the export job.
curl \
"https://api.cascade.dev/export-jobs/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@cascade-commerce/api/admin/client"
import { getExportJobsById } from "@cascade-commerce/api/admin"
client.setConfig({
baseUrl: "https://api.cascade.dev",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getExportJobsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
})require "net/http"
uri = URI("https://api.cascade.dev/export-jobs/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/export-jobs/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",
"userId": "550e8400-e29b-41d4-a716-446655440000",
"fileUrl": "string",
"type": "customers",
"status": "pending",
"totalCount": 0,
"filter": "...",
"search": "string",
"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 export job."
},
"userId": {
"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": "The user who started the export."
},
"fileUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "A signed URL to download the finished CSV. Null until the export completes."
},
"type": {
"type": "string",
"enum": [
"customers",
"products",
"orders",
"surveys",
"reviews",
"wishlists",
"loyalty-activity",
"loyalty-members",
"referrals"
],
"description": "Which records the export covers."
},
"status": {
"type": "string",
"enum": ["pending", "processing", "completed", "failed"],
"description": "Where the export has got to. Failed means the export gave up and wrote no file."
},
"totalCount": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"description": "How many rows were written, once the export finishes."
},
"filter": {
"anyOf": [
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
{
"type": "null"
}
],
"description": "The filter document the export was narrowed to. Null when the export covers every record of its type."
},
"search": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The free-text search the export was narrowed to, if there was one."
},
"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 export was started."
},
"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 export last made progress."
}
},
"required": [
"id",
"userId",
"fileUrl",
"type",
"status",
"totalCount",
"filter",
"search",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The requested export job."
}