All Collections
Other
Surfer API Documentation
Surfer API Documentation

BETA version of Surfer available via API - create queries without accessing your dashboard!

Updated over a week ago

This feature is available only if you have an Enterprise plan. Making requests is otherwise blocked, even if you have a valid API KEY.

With API requests, you can automate query creation, get shareable links and analyze data without accessing our Surfer web app through a graphical interface.
API currently interacts with:

  • Content Editor

  • Surfer AI

  • Audit

  • SERP Analyzer

All examples of the below requests are formatted to the Linux version of the cURL command - if you'd like to use it on a Windows machine, you have to adjust the syntax first.

Authentication

Surfer API uses API keys to authenticate requests. If you'd like to get your API key, please contact support via Live Chat or mail us directly at [email protected].

The API key must be included with each request in the header as API-KEY field.
Sending requests without a proper API key or without appropriate plan or add-on will result in a response of 401 "Access Denied".

Testing and sandbox

We currently do not have a sandbox environment where you could test your requests.

Every query you create via API will count towards your actual account quotas.

Having API access doesn't automatically grant you access to all tools.
If your account doesn't have access to Audit or SERP Analyzer - you won't be able to use their API endpoints.

Content Editor

Content Editor provides endpoints to:

  • create a query

  • get public hash/permalink for query access

  • specify keywords that should make up guidelines

  • download current draft text content

  • download list of suggested terms

Create a query

Schedules a new query.

  • In-app equivalent (Content Editor dashboard -> Write Yourself -> Create for 1 CE credit):

  • URL

    /api/v1/content_editors

  • Method

    POST

  • Parameters

    JSON body with the following keys:

    • keywords (required)

    • location

    • word_count

    Supported locations are available at https://app.surferseo.com/api/v1/locations. This endpoint does not require authentication.

  • Limit/Cost
    Each successful request will create one query - each query counts against your monthly/yearly limit of Content Editor queries and consumes one credit, regardless of the number of keywords specified for one analysis.

  • Example

    Request:

    curl -X POST 'https://app.surferseo.com/api/v1/content_editors' -H 'API-KEY: <your key>' -H 'Content-Type: application/json' --data-raw '{
    "keywords": ["seo research","seo article optimization"],
    "location": "United States"
    }'

    Response:

    {
    "state": "scheduled",
    "permalink_hash": "kKi7n3pkRk7Gw5cxKDiBAbCAybnDTt2z",
    "id": 5632898
    }

Get query permalink

Get the state of the query and hash that is used for generating publicly-accessible links.

  • In-app equivalent (Content Editor dashboard -> Any Content Editor query -> Share):

  • URL

    /api/v1/content_editors/:id

  • Method

    GET

  • Parameters

    JSON body with the following keys:

    • id (required)

  • Limit/Cost

    None

  • Example

    Request:

    curl -X GET 'https://app.surferseo.com/api/v1/content_editors/4141997' -H 'API-KEY: <your key>'

    Response:

    {
    "state": "completed",
    "permalink_hash": "zJ_yuVSZMaGrw7b-SI7WKfNtgaR2fNZY",
    "id": 4141997
    }

Specify guidelines keywords

Replaces words in Editor guidelines with only the ones you specify within the array.
If keyword is present in Surfer's Terms list - it will be shown under Terms to Use with a suggested range based on competitor's keyword density analysis.
If keyword is not present in Surfer's Terms list - it will be added to Terms to Use as a custom keyword with one suggested occurrence and lowest importance.

  • In-app equivalent (Any Content Editor query -> Customize -> Terms -> Bulk import terms + ticking keywords on/off):

  • URL

    /api/v1/content_editors/:id

  • Method

    PATCH

  • Parameters

    JSON body with the following keys:

    • id (required)

    • included_terms

  • Limit/Cost

    None

  • Example

    Request:

    curl -X PATCH 'https://app.surferseo.com/api/v1/content_editors/4141997' -H 'API-KEY: <your key>' -H 'Content-Type: application/json' --data-raw '{
    "included_terms":["seo is best", "seo application", "seo help"]
    }'

    Response:

    OK 

Get draft content

Get current text inserted into Editor query.
It is a clean HTML, without any CSS styles, unless you explicitly specified in text editor otherwise.

  • In-app equivalent (Content Editor dashboard -> Any Content Editor query -> (...) -> Download content as HTML):

  • URL

    /api/v1/content_editors/:id/content

  • Method

    GET

  • Parameters

    JSON body with the following keys:

    • id (required)

  • Limit/Cost

    None

  • Example

    Request:

    curl -X GET 'https://app.surferseo.com/api/v1/content_editors/4141997/content' -H 'API-KEY: <your key>'

    Response:

    {
    "content": "<h1>How to Do Keyword Research for SEO: A Beginner's Guide</h1><p>Regardless of Google s constant updates on their algorithm, one thing remains the same when it comes to optimizing a <strong>business site</strong> to be found on Google. How does keyword searching <span data-color=\"var(--red-10)\" style=\"background-color: var(--red-10); color: inherit\">help you build a good website</span>?</p><img src=\"https://images.surferseo.art/dbc7c5ef-728c-49de-b582-056b89f5d5ee.png\" alt=\"random photo of an asphalt road\"><h2>Use a Seed Keyword to Get More Keyword Ideas</h2><p>A seed keyword is a larger keyword in your niche, and this helps you to find new keyword ideas. You can search for dog foods by using the keyword “<em>dog food</em>”. Lastly, pick the location you'd like to search for. It displays suggestions for keywords based on those keywords.</p>"
    }

Download list of suggested terms

Get a list of terms we detected from SERP competitors.
It is a complete list, without additional filtering Terms to Use webapp section uses.

  • In-app equivalent (Content Editor dashboard -> Any Content Editor query -> Customize -> Terms):

  • URL

    /api/v1/content_editors/:id/terms

  • Method

    GET

  • Parameters

    JSON body with the following keys:

    • id (required)

  • Limit/Cost

    None

  • Example

    Request:

    curl -X GET 'https://app.surferseo.com/api/v1/content_editors/4141997/terms' -H 'API-KEY: <your key>'

    Response:

    {
    "terms": [
    {
    "use_in_heading": true,
    "is_nlp": false,
    "included": true,
    "ignored": false,
    "term": "things to do in poland"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "slowinski national park"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "world war ii"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "słowiński national park"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "tatra national park"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "warsaw old market place"
    },
    {
    "use_in_heading": false,
    "is_nlp": true,
    "included": false,
    "ignored": false,
    "term": "market square"
    },
    ...
    }

    Each term will additionally have following Boolean variables:

    • "is_nlp" - will be set to true if suggested term is a result of NLP analysis

    • "use_in_heading" - will be set to true if Surfer detect terms as important term to be used in headings

    • "included" - will be set to true based on:
      - your current competitor selection for the query (Customize -> Competitors)
      - your explicit term selection (Customize -> Terms)

    • "ignored" - will be set to true if your organization has banned this term from appearing in suggestions

Surfer AI

Surfer AI provides endpoints to:

  • create a Content Editor query, including Surfer AI generated draft inside

Create a query

Schedules a new query.

Request will result in either:

  • query processing through all the steps automatically, with completed AI article as a result (if you don't specify or set "manual_outline" to true)

  • query processing through initial steps automatically, and waiting for user input on AI Outline (if "manual_outline" was set to true)


Compared to in-app GUI version - you won't be able to adjust all parameters.
Query will be run with:
- Blog Post as article type
- auto-detected Organic competitors
- auto-detected Tone of voice
- Anti-AI detection boost disabled

Additionally, if you don't specify or set "manual_outline" to true, query will have:
- auto-detected Outline
- no Custom Knowledge

  • In-app equivalent (Content Editor dashboard -> Write with AI -> Create for 1 AI credit):

  • URL

    /api/v1/content_editors

  • Method

    POST

  • Parameters

    JSON body with the following keys:

    • keywords (required)

    • location

    • word_count

    • write_with_ai: true (required, otherwise it will generate a regular Editor query)

    • manual_outline

    Supported locations are available at https://app.surferseo.com/api/v1/locations. This endpoint does not require authentication.

  • Limit/Cost
    Each successful request will create one query - each query will consume one Surfer AI credit, regardless of the number of keywords specified for one analysis.
    This request won't consume any regular Content Editor credits.

  • Example

    Request:

    curl -X POST 'https://app.surferseo.com/api/v1/content_editors' -H 'API-KEY: <your key>' -H 'Content-Type: application/json' --data-raw '{
    "keywords": ["seo research","seo article optimization"],
    "location": "United States",
    "write_with_ai": true,
    "manual_outline": true
    }'

    Response:

    {
    "state": "scheduled",
    "permalink_hash": "kKi7n3pkRk7Gw5cxKDiBAbCAybnDTt2z",
    "id": 5632898,
    "ai_article_status": "new"
    }

Monitor SurferAI query status

To check for SurferAI query status changes instead of polling GET requests you can set up a webhook solution.

To do that:

  1. Set up on your end an HTTPS address which will listen for REST requests and respond with HTTP 200 OK code.

  2. Reach out to Surfer's support team via email or live chat and share the URL you prepared.

  3. We'll configure notifications on our end.

  4. From now - SurferAI query status changes will be sent to the HTTPS address you specified.

What our server will send in as a request is:

  • Method

    POST

  • Parameters
    Header with:

    • verification-key - which you can use to authenticate Surfer

    JSON body with the following keys:

    • id - notification id

    • type - one of:

      • 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 (when "manual_outline": true),

      • content_editor.ai_article.failed - generation failed

    • timestamp - ISO8601 extended UTC timestamp

    • payload - contains draft_id and permalink_hash which you can create access links with

  • Limit/Cost
    None.

  • Example
    Request:

    {
    "id": 829,
    "type": "content_editor.ai_article.completed",
    "timestamp": "2023-09-26T14:33:42Z",
    "payload": {
    "draft_id": 7965989,
    "permalink_hash": "BDId6SXX51j_185lhfe5pVijQ2ej5MP1"
    }
    }

Audit

Audit provides endpoints to:

  • create a query

  • get URLs and Content Scores of both audited URL and selected competitors

Using Audit API is available only if you have this tool included in your subscription or bought an add-on.
If tool is not available on your account, even valid requests will result in 422 "Quota exceeded".

Create a query

Schedules a new query.

  • In-app equivalent (Audit dashboard -> Create Audit):

  • URL

    /api/v1/audits

  • Method

    POST

  • Parameters

    JSON body with the following keys:

    • keywords (required)

    • url (required)

    • cache

    • device

    • location

    Supported locations are available at https://app.surferseo.com/api/v1/locations. This endpoint does not require authentication.

  • Limit/Cost

    Each successful request will create one query - each query counts against your monthly/yearly limit of Audit queries and consumes one credit.

  • Example

    Request:

    curl -X POST 'https://app.surferseo.com/api/v1/audits' -H 'API-KEY: <your key>' -H 'Content-Type: application/json' --data-raw '{
    "device": "mobile",
    "keyword": "seo research",
    "location": "United States",
    "url": "https://yourAuditedPage.com/"
    }'

    Response:

    {
    "state": "scheduled",
    "permalink_hash": "ci3XKL1EhhfX-ktOCs6iKYXRv-Umtmf1",
    "id": 767429
    }

Get a query

For a given query ID returns a list of URLs and Content scores for audited URL and selected competitors.

  • In-app equivalent (Any Audit query -> Select competitors):

  • URL

    /api/v1/audits/:id

  • Method

    GET

  • Parameters

    JSON body with the following keys:

    • ID parameter which you can get from webpage URL or from Create a query's response (required)

  • Limit/Cost

    None

  • Example

    Request:

    curl -X GET 'https://app.surferseo.com/api/v1/audits/482473' -H 'API-KEY: <your key>'

    Response:

    {
    "state": "completed",
    "permalink_hash": "ci3XKL1EhhfX-ktOCs6iKYXRv-Umtmf1",
    "id": 482473,
    "competitors_pages": [
    {
    "url": "https://www.competitor1.com/",
    "content_score": 64
    },
    {
    "url": "https://www.competitor2.com/",
    "content_score": 49
    },
    {
    "url": "https://www.competitor3.com/",
    "content_score": 55
    },
    {
    "url": "https://www.competitor4.com/",
    "content_score": 78
    },
    {
    "url": "https://www.competitor5.com/",
    "content_score": 48
    }
    ],
    "audited_page": {
    "url": "https://www.auditedURL.com/",
    "content_score": 81
    }
    }

SERP Analyzer

SERP Analyzer provides endpoints to:

  • create a query

  • create a batch of queries

  • list queries

  • get SERP competitors and data about their HTML content

  • get prominent terms from SERP competitors

Using SERP Analyzer API is available only if you have Enterprise plan or if you purchased this add-on. If tool is not available on your account, even valid requests will result in 500 "Internal server error".

Create a query

Schedules a new query.

(Fair Use policy limit applies, by default 100 queries a day.)

  • In-app equivalent (SERP Analyzer dashboard -> Create SERP Analyzer):

  • URL

    /api/v1/serp_analyzer

  • Method

    POST

  • Parameters

    JSON body with the following keys:

    • keyword (required)

    • location (required)

    • analyze_nlp_entities

    • analyze_nlp_sentiment

    • analyze_nlp_entity_sentiment

    • device

    • screenshot

    Supported locations are available at https://app.surferseo.com/api/v1/locations. This endpoint does not require authentication.

  • Limit/Cost

    Each query created will count against your daily SERP Analyzer limit (Fair Use policy limit applies, by default 100 queries a day).

  • Example

    Request:

    curl -H 'Content-Type: application/json' -H 'API-KEY: <your key>' https://app.surferseo.com/api/v1/serp_analyzer --data \  '{"keyword": "seo keyword", "location": "United States", "device": mobile}'

    Response:

    {
    "state": "scheduled",
    "id": 2117453
    }

Create a batch of queries

Schedules a batch of queries.

  • In-app equivalent (SERP Analyzer dashboard -> Create SERP Analyzer):

  • URL

    /api/v1/serp_analyzer/batches

  • Method

    POST

  • Parameters

    JSON body with an array of SERP Analyzer requests. Each query should have the same structure as when scheduling individual query.

  • Limit/Cost

    Each query created will count against your daily SERP Analyzer limit (Fair Use policy limit applies, by default 100 queries a day).

  • Example

    Request:

    curl -H 'Content-Type: application/json' -H 'API-KEY: <your key>' https://app.surferseo.com/api/v1/serp_analyzer/batches --data \  '[{"keyword": "api seo", "location": "United States"}, {"keyword": "seo life", "location": "Poland", "device": "desktop"}]'

    Response:

    [
    {
    "state": "scheduled",
    "id": 2117448
    },
    {
    "state": "scheduled",
    "id": 2117449
    }
    ]

List queries (CSV export)

Returns a CSV-style list of SERP queries.

List contains up to 5000 entries from the last month.

  • In-app equivalent (SERP Analyzer dashboard):

  • URL

    /api/v1/exports/csv/serp_analyzer

  • Method

    GET

  • Parameters

    None

  • Limit/Cost

    None

  • Example

    Request:

    curl -H 'API-KEY: <your key>' https://app.surferseo.com/api/v1/exports/csv/serp_analyzer

    Response:

    "id","state","created","location","keyword"
    "2871118","scheduled","2023-07-31 22:03:52Z","United States","how to build gaming pc"
    "2800997","completed","2023-07-12 13:53:37Z","United States","rustic wedding ideas"
    "2796112","completed","2023-07-11 10:53:21Z","United States","seo keyword"

Search results

Returns search results for a given query. The report contains URLs with SERP data, keywords and factors calculated by Surfer.

The data here highlights important page characteristics and provides high-level overview of SERP quality.

  • In-app equivalent (Any SERP Analyzer query -> Chart data + Search Results tab):

  • URL

    /api/v1/exports/csv/serp_analyzer/:id/search_results

  • Method

    GET

  • Parameters

    • ID

  • Limit/Cost

    None

  • Example

    Request:

    curl -H 'API-KEY: <your key>' https://app.surferseo.com/api/v1/exports/csv/serp_analyzer/2800997/search_results

    Response:

    "position","url","state","title/keywordCount/all","title/keywordCount/outsideLinks","meta_description/keywordCount/all","meta_description/keywordCount/outsideLinks","url/path/keywordCount/all","url/domain/keywordCount/all","body/wordCount/all","body/wordCount/outsideLinks","body/keywordCount/all","body/keywordCount/outsideLinks","p/wordCount/all","p/wordCount/outsideLinks","p/keywordCount/all","p/keywordCount/outsideLinks","p/elementCount/all","p/elementCount/outsideLinks","headings/wordCount/all","headings/wordCount/outsideLinks","headings/keywordCount/all","headings/keywordCount/outsideLinks","headings/elementCount/all","headings/elementCount/outsideLinks","above_the_fold/wordCount/all","above_the_fold/wordCount/outsideLinks","above_the_fold/keywordCount/all","above_the_fold/keywordCount/outsideLinks","h1/keywordCount/all","h1/keywordCount/outsideLinks","h2/keywordCount/all","h2/keywordCount/outsideLinks","h3/keywordCount/all","h3/keywordCount/outsideLinks","h4/keywordCount/all","h4/keywordCount/outsideLinks","h5/keywordCount/all","h5/keywordCount/outsideLinks","h6/keywordCount/all","h6/keywordCount/outsideLinks","h1/elementCount/all","h1/elementCount/outsideLinks","h2/elementCount/all","h2/elementCount/outsideLinks","h3/elementCount/all","h3/elementCount/outsideLinks","h4/elementCount/all","h4/elementCount/outsideLinks","h5/elementCount/all","h5/elementCount/outsideLinks","h6/elementCount/all","h6/elementCount/outsideLinks","img_alt/keywordCount/all","img_alt/keywordCount/outsideLinks","img_alt/wordCount/all","img_alt/wordCount/outsideLinks","img/elementCount/all","img/elementCount/outsideLinks","strong_and_b/wordCount/all","strong_and_b/wordCount/outsideLinks","strong_and_b/keywordCount/all","strong_and_b/keywordCount/outsideLinks","strong_and_b/elementCount/all","strong_and_b/elementCount/outsideLinks","score/content/all","pageSpeed/ttfb/all","pageSpeed/totalSize/all","pageSpeed/load/all"
    "1","https://www.intel.com/content/www/us/en/gaming/resources/how-to-build-a-gaming-pc.html","completed","0","0","0","0","1","0","8251","7087","0","0","5022","4885","0","0","134","134","214","139","0","0","34","34","81","68","0","0","0","0","0","0","0","0","0","0","0","0","0","0","1","1","18","18","14","14","2","2","0","0","0","0","0","0","215","205","40","38","108","92","0","0","37","37","77","99","4139.0771484375","11186"

    The exact amount of SERP results may vary depending on the specified keyword, location and device type, max top 50 competitors.

    Each row can be considered a "mini-query" with it's own "state", which can be:

    • "scheduled" - crawl and analysis of this specific competitor did not complete yet

    • "failed" - crawl did not succeed, most likely due to timeout, bot block or content paint issue

    • "completed" - crawl completed and populated data fields based on received HTML code

Prominent terms

Returns prominent words and phrases for a given query. The report includes counters for words, phrases, and their density.

  • In-app equivalent (Any SERP Analyzer query -> Prominent words and phrases tab -> Phrases and Words tabs):

  • URL

    /api/v1/exports/csv/serp_analyzer/:id/prominent_terms

  • Method

    GET

  • Parameters

    • ID

  • Limit/Cost

    None

  • Example

    Request:

    curl -H 'API-KEY: <your key>' https://app.surferseo.com/api/v1/exports/csv/serp_analyzer/2800997/prominent_terms

    Response:

    "term","pages","density_min","density_avg","density_max","words_min","words_avg","words_max"
    "pc builds","4","0.0","0.0","0.0","4.0","4.0","4.0"
    "pcie slot","4","0.0","0.0","0.0","5.0","5.0","5.0"
    "gaming performance","5","0.0","0.0","0.0","2.0","4.17","12.0"
    "best gaming","4","0.0","0.0","0.0","2.0","4.4","9.0"
    "may need","6","0.0","0.0","0.0","3.0","3.5","4.0"
    "graphics card","8","0.0","0.0","0.0","5.0","10.11","16.0"
    "graphics cards","6","0.0","0.0","0.0","2.0","2.0","2.0"
    "gaming pc","10","0.0","0.0","0.01","2.0","10.88","53.0"
    "air cooler","4","0.0","0.0","0.0","2.0","2.0","2.0"
    "pc build","7","0.0","0.0","0.01","2.0","5.88","19.0"

    The exact amount of keywords varies depending on the specified keyword and content from Google.
    Prominent Words are only populated if your selected country for the query does not support NLP analysis. With NLP on - prominent words are automatically assembled into phrases.

    Response can only be generated after SERP Analyzer query finishes loading and state is reported as "completed".

Additional resources:

Did this answer your question?