curl --request POST \
--url https://app.surferseo.com/api/v1/content_editors \
--header 'API-KEY: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"keywords": [
"How to write content that ranks?"
],
"device": "mobile",
"import_content_from_url": "https://surferseo.com/",
"location": "United States",
"manual_outline": false,
"word_count": 2137,
"write_with_ai": false
}
'import requests
url = "https://app.surferseo.com/api/v1/content_editors"
payload = {
"keywords": ["How to write content that ranks?"],
"device": "mobile",
"import_content_from_url": "https://surferseo.com/",
"location": "United States",
"manual_outline": False,
"word_count": 2137,
"write_with_ai": False
}
headers = {
"API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
keywords: ['How to write content that ranks?'],
device: 'mobile',
import_content_from_url: 'https://surferseo.com/',
location: 'United States',
manual_outline: false,
word_count: 2137,
write_with_ai: false
})
};
fetch('https://app.surferseo.com/api/v1/content_editors', 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.surferseo.com/api/v1/content_editors",
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([
'keywords' => [
'How to write content that ranks?'
],
'device' => 'mobile',
'import_content_from_url' => 'https://surferseo.com/',
'location' => 'United States',
'manual_outline' => false,
'word_count' => 2137,
'write_with_ai' => false
]),
CURLOPT_HTTPHEADER => [
"API-KEY: <api-key>",
"Content-Type: application/json"
],
]);
$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://app.surferseo.com/api/v1/content_editors"
payload := strings.NewReader("{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("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://app.surferseo.com/api/v1/content_editors")
.header("API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.surferseo.com/api/v1/content_editors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}"
response = http.request(request)
puts response.read_body{
"ai_article_status": "new",
"id": 1,
"permalink_hash": "G74SCitlYgE_N8iIYIxIS_US8yuUgsfx",
"state": "scheduled",
"workspace_id": 1
}Create Content Editor query
Deprecated. Use POST /api/v2/workspaces//content_editors instead.
Creates a new Content Editor query with an option to generate an AI article.
Use the id from a successful response to poll for state updates, as the process is asynchronous and might take a while to complete. It is only safe to render Surfer Guidelines for queries with completed state.
To check for Content Editor and AI article status changes, instead of polling GET requests you can set up a webhook solution. Refer to the Webhooks section for details on how to set it up.
You’ll receive the following payload in the webhook request body:
id- notification id (integer)type- one of:"content_editor.initialization.completed"- the Content Editor was initialized successfully"content_editor.initialization.failed"- the Content Editor initialization failed"content_editor.content_score.recalculated"- the Content Score was recalculated (after updating the content via the API)"content_editor.ai_article.completed"- whole article finished generating"content_editor.ai_article.waiting_for_user_input"- outline finished generating and is waiting for review in app (whenmanual_outline: true)"content_editor.ai_article.failed"- generation failed
timestamp- ISO8601 extended UTC timestamp (string)payload:draft_id- unique identifier of the Content Editor (integer)permalink_hash- used to share Content Editor with people (string)
Initialization events are sent for every Content Editor in your organization once a webhook URL is registered, except editors that already have an AI Article attached when initialization finishes. AI article and Content Score events are sent only for articles and content updates made through the API; an AI article started in the web app sends no webhook.
Rate limit: 10 requests/sec
Cost: one credit per successful request, regardless of the number of keywords specified for the analysis. That is a Content Editor credit, except on Enterprise and some older plans, where a request that generates an article consumes an AI article credit instead. Other plans include AI articles in the Content Editor.
curl --request POST \
--url https://app.surferseo.com/api/v1/content_editors \
--header 'API-KEY: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"keywords": [
"How to write content that ranks?"
],
"device": "mobile",
"import_content_from_url": "https://surferseo.com/",
"location": "United States",
"manual_outline": false,
"word_count": 2137,
"write_with_ai": false
}
'import requests
url = "https://app.surferseo.com/api/v1/content_editors"
payload = {
"keywords": ["How to write content that ranks?"],
"device": "mobile",
"import_content_from_url": "https://surferseo.com/",
"location": "United States",
"manual_outline": False,
"word_count": 2137,
"write_with_ai": False
}
headers = {
"API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
keywords: ['How to write content that ranks?'],
device: 'mobile',
import_content_from_url: 'https://surferseo.com/',
location: 'United States',
manual_outline: false,
word_count: 2137,
write_with_ai: false
})
};
fetch('https://app.surferseo.com/api/v1/content_editors', 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.surferseo.com/api/v1/content_editors",
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([
'keywords' => [
'How to write content that ranks?'
],
'device' => 'mobile',
'import_content_from_url' => 'https://surferseo.com/',
'location' => 'United States',
'manual_outline' => false,
'word_count' => 2137,
'write_with_ai' => false
]),
CURLOPT_HTTPHEADER => [
"API-KEY: <api-key>",
"Content-Type: application/json"
],
]);
$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://app.surferseo.com/api/v1/content_editors"
payload := strings.NewReader("{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("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://app.surferseo.com/api/v1/content_editors")
.header("API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.surferseo.com/api/v1/content_editors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"keywords\": [\n \"How to write content that ranks?\"\n ],\n \"device\": \"mobile\",\n \"import_content_from_url\": \"https://surferseo.com/\",\n \"location\": \"United States\",\n \"manual_outline\": false,\n \"word_count\": 2137,\n \"write_with_ai\": false\n}"
response = http.request(request)
puts response.read_body{
"ai_article_status": "new",
"id": 1,
"permalink_hash": "G74SCitlYgE_N8iIYIxIS_US8yuUgsfx",
"state": "scheduled",
"workspace_id": 1
}Authorizations
Headers
Workspace ID to create the content editor in. If not provided, uses the oldest active workspace.
x >= 1Body
Keywords
11 - 700["How to write content that ranks?"]
mobile, desktop URL
http(s?)://.*"https://surferseo.com/"
Location; get the list of supported locations from /api/v1/locations (no auth required)
"United States"
false will skip the outline review step and generate the AI article using the generated outline. true will pause the generation process and allow reviewing the outline on Surfer's Content Editor page.
Target word count
x >= 12137
If true, an AI article will be generated for the Content Editor. If the organization has a registered webhook handler, successful or failed article generation will trigger a webhook event.
Response
Created
Status of AI article generation
new, writing, completed, failed "new"
The unique identifier of the entity
x >= 11
Permalink hash used to share Content Editor with people
"G74SCitlYgE_N8iIYIxIS_US8yuUgsfx"
scheduled Workspace ID
1
Was this page helpful?