curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/workflows \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.base44.com/api/apps/{app_id}/workflows"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.base44.com/api/apps/{app_id}/workflows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/workflows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/workflows"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/workflows")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/workflows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"id": "68b1c0d4e7b91d003c45a1f2",
"app_id": "6820f3a4e7b91d003c45a1f2",
"name": "Email me new signups",
"status": "active",
"social_post": {
"platform": "linkedin",
"title": "Meet our new app",
"body": "Our new app is ready to try.",
"hashtags": [
"launch"
]
},
"file_key": "email-me-new-signups",
"description": "Sends an email whenever a User record is created.",
"status_reason": "consecutive_failures",
"trigger": {
"config": {
"cron_expression": "0 9 * * *",
"timezone": "UTC",
"trigger_type": "scheduled"
}
},
"total_runs": 48,
"consecutive_failures": 0,
"last_run_at": "2026-08-25T09:12:44Z",
"last_run_status": "success",
"created_date": "2026-07-02T11:04:00Z"
}
]List workflows
Returns the app’s workflows.
Archived workflows are left out unless you set include_archived. Use limit and offset to page through the results.
Passing file_keys switches this to a lookup by file name and ignores limit and offset entirely, returning every match. That is the only way to fetch more than 200 workflows in one call, and it is meant for resolving names you already hold rather than for paging.
The response omits each workflow’s definition. Get a single workflow with Get workflow when you need the definition.
curl --request GET \
--url https://app.base44.com/api/apps/{app_id}/workflows \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.base44.com/api/apps/{app_id}/workflows"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.base44.com/api/apps/{app_id}/workflows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.base44.com/api/apps/{app_id}/workflows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.base44.com/api/apps/{app_id}/workflows"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.base44.com/api/apps/{app_id}/workflows")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/workflows")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body[
{
"id": "68b1c0d4e7b91d003c45a1f2",
"app_id": "6820f3a4e7b91d003c45a1f2",
"name": "Email me new signups",
"status": "active",
"social_post": {
"platform": "linkedin",
"title": "Meet our new app",
"body": "Our new app is ready to try.",
"hashtags": [
"launch"
]
},
"file_key": "email-me-new-signups",
"description": "Sends an email whenever a User record is created.",
"status_reason": "consecutive_failures",
"trigger": {
"config": {
"cron_expression": "0 9 * * *",
"timezone": "UTC",
"trigger_type": "scheduled"
}
},
"total_runs": 48,
"consecutive_failures": 0,
"last_run_at": "2026-08-25T09:12:44Z",
"last_run_status": "success",
"created_date": "2026-07-02T11:04:00Z"
}
]Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the app whose workflows you want to work with.
Query Parameters
Include archived workflows in the results.
Most workflows to return.
1 <= x <= 200How many workflows to skip, for paging.
x >= 0Look workflows up by their file name instead of paging. Repeat the parameter for several. At most 50, each at most 256 characters and free of path separators.
Response
The app's workflows.
ID of the workflow.
"68b1c0d4e7b91d003c45a1f2"
ID of the app the workflow belongs to.
"6820f3a4e7b91d003c45a1f2"
Name of the workflow.
"Email me new signups"
Whether the workflow runs: active, inactive, or archived. See Workflow status for what each means and how it changes.
"active"
Current post content for a social publishing workflow, or null when no linked post is available.
Show child attributes
Show child attributes
Name of the workflow's file in the app's code.
"email-me-new-signups"
What the workflow is for.
"Sends an email whenever a User record is created."
Why Base44 changed the workflow's status on its own, as one of consecutive_failures, end_condition_reached, migration_activation_failed, or workflows_not_available. This is null when you changed the status yourself. See Workflow status for what each code means.
"consecutive_failures"
What starts the workflow. The trigger sits under config, keyed by trigger_type.
{
"config": {
"cron_expression": "0 9 * * *",
"timezone": "UTC",
"trigger_type": "scheduled"
}
}
Runs the workflow has started, ever.
48
Runs that have failed in a row.
0
When the workflow last started running, as an ISO 8601 UTC timestamp. This is null before its first run.
"2026-08-25T09:12:44Z"
How the workflow's most recent run ended: success, failed, or cancelled. This is null before the first run. See Workflow status for how this compares to a run's own status.
"success"
When the workflow was created, as an ISO 8601 UTC timestamp.
"2026-07-02T11:04:00Z"
Was this page helpful?