What runs in the background
Six operations start work that outlives the response; the table says what each request answers, where to poll, and which states are final.Content Editor states
Afailed editor has no retry call; read error.reason and create a new one.
AI Article states
An article pauses inwaiting_for_user_input only when you created it with manual_outline: true.
Auto-Optimize states
A completed job also carries aresult, so check it before you read the content again.
Recognizing a fresh score
A score is fresh whenstatus is ready and calculated_at is later than the value you read before the update.
After Update Content Editor content returns
204, the SEO status flips to calculating at once. A ready AI Search score flips too, unless the editor’s AI Search guidelines have not finished generating; then that score stays as it was and only the SEO score recalculates. calculated_at is null until the first calculation completes.
Combined Content Score
The editor’scontent_score object on Get Content Editor carries seo, ai_search, and total. total is the rounded average of the two, capped at 100, when both exist, and equals seo when the AI Search score is missing.
Set up a webhook
One HTTPS URL per organization receives every event; support registers it and gives you the verification key.1
Serve an HTTPS endpoint
Serve an HTTPS URL that accepts
POST requests with a JSON body.2
Answer with a 2xx status within 30 seconds
Queue the body and answer before you process it. An answer after 30 seconds
counts as a failed delivery (Delivery).
3
Ask support to register the URL
Send the URL through the same support channel as your API key
(Authentication). Support registers
it for your organization and replies with the verification key.
4
Store the verification key
Keep it where your endpoint can read it, for example in an environment
variable.
5
Reject deliveries with a different key
Compare the
verification-key header of each request with the stored key,
and drop bodies whose key differs.6
Create a test Content Editor
This spends one Content Editor credit (Rate limits and
credits). Call Create Content
Editor with any keyword.
7
Wait for the first event
content_editor.initialization.completed arrives when initialization
finishes and carries the editor’s id as draft_id.Delivery
Each event is onePOST with a JSON body and the verification key in a header. Your response status decides whether Surfer marks the delivery done, retries it, or stops.
A delivery looks like this, here for content_editor.initialization.completed:
Deliveries can arrive out of order: a retried event lands after events that came later. If your endpoint processed a delivery but answered late, the retry brings the same
id again.
A failed SEO recalculation runs a second time, so one content update can send content_editor.seo_score.failed twice, or once before content_editor.seo_score.calculated. Keep the polling endpoints above as the way to re-sync after a gap.
Which work sends events
Most events are sent only for work started through the API; work started in the Surfer app sends none, with one exception.Event catalog
Every event names the Content Editor:draft_id is the editor’s id, and permalink_hash is the hash of its edit link (List Content Editor permalinks).
The AI Article events carry no article id. Use
draft_id to list the editor’s articles and read the newest one.