curl --request POST \
--url https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Workspace-Id: <x-workspace-id>' \
--data '{}'import requests
url = "https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief"
payload = {}
headers = {
"X-Workspace-Id": "<x-workspace-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Workspace-Id': '<x-workspace-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
};
fetch('https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief', 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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief",
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([
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-Workspace-Id: <x-workspace-id>"
],
]);
$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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Workspace-Id", "<x-workspace-id>")
req.Header.Add("Authorization", "Bearer <token>")
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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief")
.header("X-Workspace-Id", "<x-workspace-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Workspace-Id"] = '<x-workspace-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"data": {
"briefId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created": true,
"planId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"data": {
"briefId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created": true,
"planId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}Write a Brief for a content-gap action
Accepts a content_gap action and creates the content work for it, like Write Brief in the app: a Content Brief and a plan with one target per market, prepared for approval. It moves the action to in_progress. Nothing is written or charged against the article allowance until the plan is approved; preparing it runs the planner, so this is rate limited on the pipeline tier. Returns briefId, created and planId; read the Brief with GET /briefs/{id}. Today the Brief is prepared as a Content Agent plan that waits for approval (planId): check it with GET /content-agent/plans/{planId}, approve it with POST /content-agent/plans/{planId}/approve to start writing, then poll GET /briefs/{id}/run for the Articles. When no plan is created, planId is null and the Brief is a draft: run it with POST /briefs/{id}/run. Idempotent per action: when the action already has content work, the same Brief and plan come back with created: false (200), so a retry never makes a second plan; an Idempotency-Key header is accepted but not needed. If the gap already has a Brief, the plan uses that Brief instead of creating another. Only content_gap actions qualify (422 otherwise, naming the source); a done or declined action is 422 until restored. 403 when Content Agent planning is not enabled for the workspace or the Content Agent is paused (a pause that lands while the plan is being prepared is a 404 instead). Requires write access and an editor-level role.
curl --request POST \
--url https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'X-Workspace-Id: <x-workspace-id>' \
--data '{}'import requests
url = "https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief"
payload = {}
headers = {
"X-Workspace-Id": "<x-workspace-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Workspace-Id': '<x-workspace-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
};
fetch('https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief', 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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief",
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([
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"X-Workspace-Id: <x-workspace-id>"
],
]);
$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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Workspace-Id", "<x-workspace-id>")
req.Header.Add("Authorization", "Bearer <token>")
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://www.getsurfaced.ai/api/v1/actions/{id}/write-brief")
.header("X-Workspace-Id", "<x-workspace-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.getsurfaced.ai/api/v1/actions/{id}/write-brief")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Workspace-Id"] = '<x-workspace-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_body{
"data": {
"briefId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created": true,
"planId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"data": {
"briefId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"created": true,
"planId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "<string>",
"details": {}
}
}Authorizations
API key (sk_live_...) created at https://www.getsurfaced.ai/app/settings/account/api-keys
Headers
Body
The body is of type object.