Skip to main content
Match the status and body you received against a heading below. Every status and reason the API returns is listed on Errors; this page covers the cases that table cannot settle by itself.

Connecting and authenticating

Check the request URL and the API-KEY header first.

An HTML page comes back instead of JSON

The request went to a path that no API endpoint serves, so it fell through to the web app’s HTML not-found page. Check that the URL starts with https://app.surferseo.com/api/v2/ and that the path matches the endpoint’s reference page (URLs and versions). A JSON 404 with "reason": "route_not_found" in details means the prefix is right and the rest of the path is wrong.

401 although the key is in the request

Surfer reads the key only from the API-KEY header, so a key sent as Authorization: Bearer, in a query parameter, or under another header name is not seen. Send it as API-KEY: <your key> (Send the key with every request). If the header is right, check that you hold the current key (Get your API key).

403 with a valid key

The key is recognized, but the plan behind it has no API access, API access is not enabled for your organization, or on a v1 tool endpoint the plan lacks that tool. When authentication fails has the check for each case and says when to write to support.

404 on a workspace path

The workspace in the path is not one your key can use: it belongs to another organization or is not active. Pick an id whose state is active from List workspaces; Workspaces in the path has the rule. The same shape with "entity": "content_editor" means the editor id is not in that workspace.

Requests that are rejected or come back empty

Use the response’s reason and details to identify the rejected input.

409 with Content editor must be in completed state

The Content Editor has not finished its analysis. Check the editor’s state with Get Content Editor. Continue when it is completed; when it is failed, read its error before you create another editor, which spends a credit (Content Editor states, Credits).

413 on a content update, or 400 with too_large on an outline submit

The body is over the 1,000,000 bytes that Update Content Editor content and Submit edited AI Article outline each read. Trim the document, for example by removing embedded images and inline styles, and send it again.

422 with quota_exceeded

The organization has used up the allowance the operation spends, or holds as many templates or voices as its plan allows; the message names the allowance, for example Content Editor quota exceeded or Auto-Optimize allowance exceeded. Credits says what each operation spends and what to do when an allowance runs out.

429 on a burst of requests

The request went over the rate limit. Wait the number of seconds in the Retry-After header, then retry, and spread bulk work instead of bursting (Over the limit).

An empty data list where Content Editors exist

Content Editor lists cover the 90 days before now unless you pass filter[inserted_after] or filter[inserted_before], so older editors fall outside the window. Move the window to the dates the missing editors were created (The 90-day window on Content Editor lists).

422 from AI Detector or Humanizer on v1

Either text is outside the length the tool accepts, or the tool refused the run; the body says which.
  • For Detect AI content in a text, split text over 100,000 characters into shorter pieces.
  • For Humanize text, skip text shorter than 128 characters.
  • When text is within its limit, read the JSON body. Quota exceeded means the Humanizer allowance is used up (Credits). Unknown error from AI Detector or Failed generation, please try again later from Humanizer means the run failed: retry once, then write to support.

500 on a content read or update

GET .../content and PUT .../content answer 500 with "reason": "internal_error" when Surfer could not reach or back up the editor’s document.
  1. Retry the request after a moment.
  2. If it fails again for the same editor, write to support with the editor id.

Work that does not finish

Check the resource’s current state before you start another run.

The AI Article or the Auto-Optimize job never reaches completed

An AI Article (an article Surfer writes inside a Content Editor) and an Auto-Optimize job (a rewrite Surfer applies to the editor’s document) both run in the background, and failed is final for both. Read the state on Get AI Article or Get Auto-Optimize job, then:
  • waiting_for_user_input: the article was created with manual_outline: true and waits for your outline. Submit it to resume writing; Generate an article with outline review has the steps.
  • new for a long time: the article waits for the editor’s guidelines to settle, and fails on its own if they never do.
  • failed: start a new article or job. A new Auto-Optimize run counts toward your plan’s Auto-Optimize allowance; a new article spends an AI Article credit on Enterprise and some older plans, while other plans include AI Articles in the Content Editor (Credits).
AI Article states and Auto-Optimize states give the meaning of every state.

The SEO score never leaves calculating

A failed recalculation leaves status at calculating, so a poll without a deadline never ends (Recognizing a fresh score).
  1. When your polling deadline passes or content_editor.seo_score.failed arrives, write the content again with Update Content Editor content to start a new recalculation.
  2. If the score stays at calculating again, write to support with the editor id.

A v1 SERP Analyzer export answers 404 Not found. or has rows with empty values

Get search results and Get prominent terms answer the plain-text 404 Not found. while the query is still running, when the id is not one of your organization’s queries, and, for prominent terms, when no prominent words or phrases were found.
  1. Poll List SERP Analyzer queries for a workspace until the query’s state is completed. failed is final; v1 has no retry, so create a new query.
  2. Fetch the reports.
In the search results report, every row carries its own state: a scheduled row is still being crawled, a failed row was not crawled, and both have empty values in the factor columns. SERP competitor exports has the full recipe.

Webhooks and integrations

Check the receiver’s response status and its verification key.

No webhook arrives

A delivery counts only when the registered HTTPS URL answers 2xx in time. Check, in order:
  1. Confirm the URL is public and uses HTTPS.
  2. Confirm the receiver answers 2xx before it does any work; Delivery has the deadline and the retry rules.
  3. Check that the work you started sends the event you wait for (Which work sends events).
  4. Compare the key your receiver checks with the current verification key (Set up a webhook).

Requests from Make or n8n fail authentication

Surfer reads the key only from the API-KEY header. In the tool’s HTTP request, add a custom header named API-KEY with your key as its value instead of the tool’s built-in authentication options, and use the URL from the endpoint’s reference page (Send the key with every request).

When a fix does not hold

Remove your API key from anything you send, then write to [email protected] with:
  • The method and path, for example PUT /api/v2/workspaces/123/content_editors/456/content.
  • The time of the request, with its time zone.
  • The full response: status, headers, and body. The x-request-id header lets support find the request in Surfer’s logs.