curl --request POST \
--url https://api.peec.ai/customer/v1/actions/list \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"project_id": "or_f45b94ba-5e35-4982-93ed-285e72ee14eb",
"types": [],
"statuses": [],
"categories": [],
"domains": [
"example.com"
],
"topic_ids": [
"to_a1b2c3"
],
"model_channel_ids": [
"openai-0"
],
"country_codes": [
"US"
],
"targets": [],
"groups": [],
"archetypes": [],
"platforms": [
"reddit.com"
],
"order_by": "impact",
"direction": "desc",
"limit": 1000,
"offset": 0
}
'import requests
url = "https://api.peec.ai/customer/v1/actions/list"
payload = {
"project_id": "or_f45b94ba-5e35-4982-93ed-285e72ee14eb",
"types": [],
"statuses": [],
"categories": [],
"domains": ["example.com"],
"topic_ids": ["to_a1b2c3"],
"model_channel_ids": ["openai-0"],
"country_codes": ["US"],
"targets": [],
"groups": [],
"archetypes": [],
"platforms": ["reddit.com"],
"order_by": "impact",
"direction": "desc",
"limit": 1000,
"offset": 0
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: 'or_f45b94ba-5e35-4982-93ed-285e72ee14eb',
types: [],
statuses: [],
categories: [],
domains: ['example.com'],
topic_ids: ['to_a1b2c3'],
model_channel_ids: ['openai-0'],
country_codes: ['US'],
targets: [],
groups: [],
archetypes: [],
platforms: ['reddit.com'],
order_by: 'impact',
direction: 'desc',
limit: 1000,
offset: 0
})
};
fetch('https://api.peec.ai/customer/v1/actions/list', 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://api.peec.ai/customer/v1/actions/list",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => 'or_f45b94ba-5e35-4982-93ed-285e72ee14eb',
'types' => [
],
'statuses' => [
],
'categories' => [
],
'domains' => [
'example.com'
],
'topic_ids' => [
'to_a1b2c3'
],
'model_channel_ids' => [
'openai-0'
],
'country_codes' => [
'US'
],
'targets' => [
],
'groups' => [
],
'archetypes' => [
],
'platforms' => [
'reddit.com'
],
'order_by' => 'impact',
'direction' => 'desc',
'limit' => 1000,
'offset' => 0
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.peec.ai/customer/v1/actions/list"
payload := strings.NewReader("{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.peec.ai/customer/v1/actions/list")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peec.ai/customer/v1/actions/list")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "01a0422f-e0c4-7820-85a1-31515a321f15",
"type": "TEMPLATE_ACTION",
"status": "PENDING",
"title": "Add a pricing comparison table to the plans page",
"group": "OWNED",
"category": "EDITORIAL_PITCH",
"target": "owned",
"archetype": "HOMEPAGE",
"platform": "reddit.com",
"topic_id": "to_a1b2c3",
"source": "https://example.com/pricing",
"domain": "example.com",
"country_codes": [
"<string>"
],
"model_channel_ids": [
"openai-0"
],
"impact": "VERY_LOW",
"step_count": 123,
"completed_step_count": 123,
"created_at": "2026-08-20T10:12:00.000Z",
"status_updated_at": "<string>",
"created_by": "peec",
"priority": "none",
"assignee_user_id": "<string>",
"due_on": "2026-10-31",
"tag_ids": [
"<string>"
]
}
],
"total_count": 42
}List Actions
The project’s actions, the ones Peec generated and the ones the customer wrote themselves alike: what to do, on which page or site, and how much impact it is expected to have if it is done. created_by says which of the two an action is, and only a customer’s own can be deleted or reshaped. Filters combine with AND, except targets, groups, archetypes and platforms, which combine with OR across the four. The action detail endpoint carries a single action’s steps, brief, evidence and impacted prompts.
curl --request POST \
--url https://api.peec.ai/customer/v1/actions/list \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"project_id": "or_f45b94ba-5e35-4982-93ed-285e72ee14eb",
"types": [],
"statuses": [],
"categories": [],
"domains": [
"example.com"
],
"topic_ids": [
"to_a1b2c3"
],
"model_channel_ids": [
"openai-0"
],
"country_codes": [
"US"
],
"targets": [],
"groups": [],
"archetypes": [],
"platforms": [
"reddit.com"
],
"order_by": "impact",
"direction": "desc",
"limit": 1000,
"offset": 0
}
'import requests
url = "https://api.peec.ai/customer/v1/actions/list"
payload = {
"project_id": "or_f45b94ba-5e35-4982-93ed-285e72ee14eb",
"types": [],
"statuses": [],
"categories": [],
"domains": ["example.com"],
"topic_ids": ["to_a1b2c3"],
"model_channel_ids": ["openai-0"],
"country_codes": ["US"],
"targets": [],
"groups": [],
"archetypes": [],
"platforms": ["reddit.com"],
"order_by": "impact",
"direction": "desc",
"limit": 1000,
"offset": 0
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
project_id: 'or_f45b94ba-5e35-4982-93ed-285e72ee14eb',
types: [],
statuses: [],
categories: [],
domains: ['example.com'],
topic_ids: ['to_a1b2c3'],
model_channel_ids: ['openai-0'],
country_codes: ['US'],
targets: [],
groups: [],
archetypes: [],
platforms: ['reddit.com'],
order_by: 'impact',
direction: 'desc',
limit: 1000,
offset: 0
})
};
fetch('https://api.peec.ai/customer/v1/actions/list', 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://api.peec.ai/customer/v1/actions/list",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'project_id' => 'or_f45b94ba-5e35-4982-93ed-285e72ee14eb',
'types' => [
],
'statuses' => [
],
'categories' => [
],
'domains' => [
'example.com'
],
'topic_ids' => [
'to_a1b2c3'
],
'model_channel_ids' => [
'openai-0'
],
'country_codes' => [
'US'
],
'targets' => [
],
'groups' => [
],
'archetypes' => [
],
'platforms' => [
'reddit.com'
],
'order_by' => 'impact',
'direction' => 'desc',
'limit' => 1000,
'offset' => 0
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.peec.ai/customer/v1/actions/list"
payload := strings.NewReader("{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.peec.ai/customer/v1/actions/list")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.peec.ai/customer/v1/actions/list")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"project_id\": \"or_f45b94ba-5e35-4982-93ed-285e72ee14eb\",\n \"types\": [],\n \"statuses\": [],\n \"categories\": [],\n \"domains\": [\n \"example.com\"\n ],\n \"topic_ids\": [\n \"to_a1b2c3\"\n ],\n \"model_channel_ids\": [\n \"openai-0\"\n ],\n \"country_codes\": [\n \"US\"\n ],\n \"targets\": [],\n \"groups\": [],\n \"archetypes\": [],\n \"platforms\": [\n \"reddit.com\"\n ],\n \"order_by\": \"impact\",\n \"direction\": \"desc\",\n \"limit\": 1000,\n \"offset\": 0\n}"
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "01a0422f-e0c4-7820-85a1-31515a321f15",
"type": "TEMPLATE_ACTION",
"status": "PENDING",
"title": "Add a pricing comparison table to the plans page",
"group": "OWNED",
"category": "EDITORIAL_PITCH",
"target": "owned",
"archetype": "HOMEPAGE",
"platform": "reddit.com",
"topic_id": "to_a1b2c3",
"source": "https://example.com/pricing",
"domain": "example.com",
"country_codes": [
"<string>"
],
"model_channel_ids": [
"openai-0"
],
"impact": "VERY_LOW",
"step_count": 123,
"completed_step_count": 123,
"created_at": "2026-08-20T10:12:00.000Z",
"status_updated_at": "<string>",
"created_by": "peec",
"priority": "none",
"assignee_user_id": "<string>",
"due_on": "2026-10-31",
"tag_ids": [
"<string>"
]
}
],
"total_count": 42
}Authorizations
Body
Required if using a company api key
"or_f45b94ba-5e35-4982-93ed-285e72ee14eb"
Defaults to every published type. TEMPLATE_ACTION is a per-platform playbook filled in for one page; CONTENT_BRIEF and CATEGORY_SITUATION_BRIEF are net-new content to write; CONTRADICTIONS_EXTERNAL_SOURCES requests correction of one third-party source page that conflicts with a verified brand fact; CONTRADICTIONS_OWNED_SOURCES corrects one source page on a domain the brand owns; SEO_ISSUE and ROBOTS_TXT are technical fixes to a site the brand controls; PDP_OPTIMISATION improves one product page; MANUAL_ACTION is work a customer described themselves that matches none of the other shapes; CONTENT_OPTIMISATION improves an existing page the brand owns, and appears only on projects with content optimisation enabled — the optimize content endpoint returns its article, suggestions and score.
TEMPLATE_ACTION, CONTENT_BRIEF, CATEGORY_SITUATION_BRIEF, CONTRADICTIONS_EXTERNAL_SOURCES, CONTRADICTIONS_OWNED_SOURCES, SEO_ISSUE, ROBOTS_TXT, PDP_OPTIMISATION, MANUAL_ACTION, CONTENT_OPTIMISATION Defaults to every status. PENDING is untouched, ACCEPTED is in progress, COMPLETED is done, REJECTED was declined.
PENDING, ACCEPTED, REJECTED, COMPLETED The off-site playbook a template action follows (the upper-case values), or the audit check an SEO_ISSUE came from (the lower-case ones). A playbook is orthogonal to the group, so the same one appears across groups, and narrowing by both means the intersection. Content briefs and ROBOTS_TXT actions carry none and match nothing here.
EDITORIAL_PITCH, LISTICLE_COMPARISON_INCLUSION, REVIEW_DIRECTORY_OPTIMIZATION, COMMUNITY_ENGAGEMENT, SOCIAL_CONTENT, accessibility, canonical, crawlability, dom_health, blocked, not_found, other, rate_limited, unavailable, metadata, performance, retrievability, schema, semantic_html, structure, structured_data The site an SEO_ISSUE was raised against. Every other type carries none and matches nothing here.
["example.com"]
Only actions on these topics (see the topics endpoint).
["to_a1b2c3"]
Only actions affecting these AI engine channels (see the model channels endpoint).
openai-0, openai-1, qwen-0, openai-2, perplexity-0, perplexity-1, google-0, google-1, google-2, google-3, google-4, anthropic-0, anthropic-1, anthropic-2, anthropic-3, deepseek-0, meta-0, meta-1, xai-0, xai-1, microsoft-0, amazon-0, mistral-0, mistral-1, naver-0, openai-3, openai-4, openai-5 ["openai-0"]
ISO 3166-1 alpha-2 markets. An action carrying no markets is not scoped to one, so every selection matches it.
AE, AL, AM, AR, AT, AU, BA, BE, BG, BH, BO, BR, BS, BY, CA, CH, CL, CN, CO, CR, CY, CZ, DE, DK, DO, EC, EE, EG, ES, FI, FR, GB, GE, GH, GR, GT, HK, HN, HR, HU, ID, IE, IL, IN, IQ, IS, IT, JO, JP, KR, KW, LB, LI, LT, LU, LV, MA, MD, ME, MK, MN, MT, MX, MY, NG, NI, NL, NO, NZ, OM, PK, PA, PE, PH, PL, PT, PY, PS, QA, RO, RS, SA, SE, SG, SI, SK, SV, TH, TN, TR, TW, UA, US, UY, VE, VN, ZA, AD, AF, AS, AZ, BB, BQ, CG, CI, CM, CW, DM, DZ, FO, GF, GP, JM, KG, KH, KI, KZ, LK, LR, LS, MW, NC, PG, TD, TF, UG, VU, ZW ["US"]
owned means the action lands on a page the brand controls; earned means a third-party page, which covers editorial coverage and community posts alike. A UGC action is earned even when the brand writes the post itself.
owned, earned The kind of surface the action lands on.
OWNED, EDITORIAL, REFERENCE, UGC, OTHER The kind of page a content brief says to create. Template actions carry no archetype and match nothing here, so this narrows the answer to content briefs.
HOMEPAGE, CATEGORY_PAGE, PRODUCT_PAGE, LISTICLE, COMPARISON, PROFILE, ALTERNATIVE, DISCUSSION, HOW_TO_GUIDE, ARTICLE, OTHER Registrable domain of a third-party action. Own-site actions carry none and match nothing here.
["reddit.com"]
impact is the order the Actions page ranks by, strongest expected gain first. created_at reads newest first, which is how to find what Peec generated since the last read.
impact, created_at asc, desc 1 <= x <= 100000 <= x <= 9007199254740991