Migrate Projects API from v3 to v4

This guide provides step-by-step instructions for migrating your Semrush Projects API integrations from v3 to v4.

It covers changes to endpoints, request parameters, and response formats for project management, Position Tracking, and Site Audit, with a practical migration example for each.

Jump to Before you startBefore you start

Before migrating your integration:

  1. List the v3 methods your application uses in each of the Projects API groups: project management, Position Tracking, and Site Audit.
  2. Prepare a test environment where you can compare v3 and v4 results.

Jump to Step 1. Get v4 API keyStep 1. Get v4 API key

API v3 and v4 use version-specific API keys. You need a v4 API key to authenticate requests to v4 endpoints.

  1. Create a v4 API key.
  2. Configure the required permissions and optionally set an expiration date for added security.
  3. Store the API key securely.
  4. Update your integration to use the new key.

Pass your API key in the Authorization header:

HTTP
Authorization: Apikey YOUR_API_KEY

For more information, refer to API v4 authorization.

Jump to Step 2. Find corresponding v4 endpointsStep 2. Find corresponding v4 endpoints

API group
v4 base path
Projects
/apis/v4/projects/v1/projects
Position Tracking
/apis/v4/position-tracking/v1/seo/campaigns
Site Audit
/apis/v4/site-audit/v1/campaigns

To identify the correct replacement:

  1. Find the v3 method in the v3 and v4 comparison reference. Look in the Project management, Position Tracking, and Site Audit sections.
  2. Identify the equivalent v4 endpoint or endpoints.
  3. Check if reproducing the same result requires multiple v4 requests.

For example, v3 Get information about campaign is replaced by five v4 Site Audit endpoints: campaign details, crawl settings, audit progress, audit report, and linking report. For a full walkthrough of a Site Audit use case, refer to Example 3.

If a method isn’t covered by v4, check its status in the comparison reference. For example, v4 doesn’t need the v3 Get text descriptions about issues method, because it identifies issues by self-descriptive issue_type values, such as INTERNAL_LINK_BROKEN.

Jump to Step 3. Update your API requestsStep 3. Update your API requests

After identifying the corresponding v4 endpoints, update your request URLs, parameters, and response handling.

Jump to Update endpoint URLsUpdate endpoint URLs

Replace the v3 endpoint, including any type parameter and ID in the URL, with the v4 endpoint from the method mapping.

Check how each ID is passed:

  • Project ID. Get, Update, and Delete Project take it as the project_id path parameter.
  • Position Tracking campaign ID. Campaign-level methods take it as the campaign_id path parameter. To find a campaign, use List Project Campaigns.
  • Site Audit campaign ID. It’s the same as the project ID.

Jump to Update request parametersUpdate request parameters

Some parameters are renamed, reorganized, or replaced in v4. For example:

  • Project management: filter becomes scope, and url becomes domain. The v4 List Projects method also supports limit and offset for pagination.
  • Position Tracking: channel selects organic or paid data, and dates use the YYYY-MM-DD format instead of YYYYMMDD. Each report request takes one target_url.
  • Site Audit: snapshot_id becomes audit_report_id, numeric issue IDs become issue_type values, and crawl settings are nested in settings.

Review the request parameter differences for each method before updating your integration.

Jump to Update response handlingUpdate response handling

Response formats and field names differ between v3 and v4. For example:

  • Project fields move from the top level of the response to data.
  • permission codes become a permissions object with Boolean fields.
  • Site Audit dates change from Unix timestamps in milliseconds to ISO 8601 UTC strings.
  • Position Tracking values for each tracking date are grouped in tracking_points.

In v4, JSON responses separate metadata in meta from results in data.

If your integration parses API responses, update it to handle the new field names and structure.

For a complete list of changes, refer to Response parameter differences. For step-by-step examples, refer to Migration examples.

Jump to Step 4. Test your updated integrationStep 4. Test your updated integration

Before switching production requests to v4, test your updated integration.

  1. Confirm that your v4 API key has the necessary permissions.
  2. Check that your application can call the v4 endpoints.
  3. Make sure your application correctly processes v4 responses.
  4. Confirm that v4 returns the data your use cases require, for the same projects and campaigns.
  5. Verify that multi-request workflows retrieve and process all required data.
  6. Check API Unit consumption and limits, especially for multi-request workflows and for endpoints billed per item, such as per keyword, page, tag or competitor.
  7. Make sure your integration handles v4 errors correctly.

When comparing results, pay particular attention to changes in field names, data types, date formats, and data availability.

Jump to Step 5. Switch to v4Step 5. Switch to v4

Once your updated integration has been tested:

  1. Switch the verified operations from v3 to v4.
  2. Monitor the integration for errors and unexpected results.
  3. Check API Unit consumption.
  4. Continue migrating any remaining supported v3 methods.
  5. Remove unused v3-specific configuration after completing the migration.

Jump to Migration examplesMigration examples

The following examples demonstrate how to migrate commonly used Projects API use cases from v3 to v4.

They cover different migration scenarios:

  • Replacing an endpoint and updating request parameters and the response structure.
  • Replacing a single v3 filter with v4 filter parameters and one request per target.
  • Replacing a sequence of v3 requests with the v4 workflow.

For other methods, refer to the Semrush API v3 and v4 comparison reference.

Jump to Example 1. Migrate List ProjectsExample 1. Migrate List Projects

Use this example if your integration retrieves your projects to find a project ID, or to check which tools are enabled for a project.

In v3, use List All Existing Projects:

HTTP
GET /management/v1/projects

In v4, use the List Projects endpoint:

HTTP
GET /apis/v4/projects/v1/projects

What you need to change:

  1. Replace the v3 endpoint with the v4 List Projects endpoint.
  2. Replace filter with scope, and change its values to uppercase. For example, filter=all becomes scope=ALL.
  3. Pass your v4 API key in the Authorization header.
  4. If you have many projects, use pagination. limit defaults to 100 and can be up to 1000. Use offset to skip projects. meta.total_count returns the total number of projects matching the scope.
  5. Update your response parser:
    • Read the list of projects from data.
    • If your application reads the project domain from url, update it to read domain.
    • If your application checks permission codes, update it to read the Boolean fields in the permissions object: read, edit, delete, share, and downgraded.
    • If your application reads the tool identifier from tools[].tool, update it to read tools[].name.

Sample requests and responses:

v3 request
Shell
curl "https://api.semrush.com/management/v1/projects?key=YOUR_API_KEY&filter=all"
v3 response
JSON
[
    {
        "url": "mysite.com",
        "domain_unicode": "mysite.com",
        "tools": [
            {
                "tool": "tracking"
            }
        ],
        "project_id": 643526670283248,
        "project_name": "myproject",
        "owner_id": 123456780,
        "permission": [
            "OWNER"
        ]
    }
]
v4 request
Shell
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/projects/v1/projects?scope=ALL&limit=100&offset=0"
v4 response
JSON
{
    "meta": {
        "request_id": "182d587194adf5096d1b6d5b309f164f",
        "status_code": 200,
        "success": true,
        "scope": "ALL",
        "limit": 100,
        "offset": 0,
        "total_count": 1
    },
    "data": [
        {
            "project_id": 643526670283248,
            "project_name": "Main website",
            "domain": "example.com",
            "domain_unicode": "example.com",
            "owner_id": 123456780,
            "permissions": {
                "read": true,
                "edit": true,
                "delete": true,
                "share": true,
                "downgraded": false
            },
            "tools": [
                {
                    "name": "site_audit"
                },
                {
                    "name": "position_tracking"
                }
            ]
        }
    ]
}

The other project management methods follow the same pattern. The id path parameter becomes project_id. For Update Project, the project ID moves from the request body to the project_id path parameter, and v4 uses PATCH instead of PUT. For details, refer to the Project management mapping.

Jump to Example 2. Migrate AI Overview keyword tracking (Position Tracking)Example 2. Migrate AI Overview keyword tracking (Position Tracking)

Use this example if your integration checks which tracked keywords trigger Google AI Overview, and whether your domain or a competitor is included in it.

In v3, you retrieve this data with the Organic positions report. The serp_feature_filter parameter selects the keywords:

HTTP
GET /reports/v1/projects/{campaignID}/tracking/?type=tracking_position_organic

In v4, use the Get Seo Overview endpoint:

HTTP
GET /apis/v4/position-tracking/v1/seo/campaigns/:campaign_id/reports/overview

In v3, one request can list several domains in url, and serp_feature_filter refers to a domain by its position in that list. For example, aio,0 selects the keywords where the first domain ranks in AI Overview, and aio,1 selects the keywords where the second domain does.

In v4, each request has one target, so this use case takes one request per domain.

Jump to Step 1. Get the campaign ID and datesStep 1. Get the campaign ID and dates

Unlike v3, Get Seo Overview requires channel, base_date, and comparison_date. Get the campaign ID and dates first:

  1. Get the campaign_id of your campaign with List Project Campaigns.
  2. Get the dates with collected data with Get Campaign Tracking Points.
  3. Choose base_date and comparison_date from the returned dates.

Jump to Step 2. Update request parametersStep 2. Update request parameters

v3 parameter
v4 parameter
What changed
type=tracking_position_organic
Endpoint URL, channel=ORGANIC
A dedicated endpoint replaces type. channel is required.
url with several domains separated by :
target_url
Send a separate request for each target. Omit target_url to use the campaign target.
date_begin, date_end
base_date, comparison_date
Dates change from YYYYMMDD to YYYY-MM-DD. Both parameters are required.
serp_feature_filter=aio
serp_features=AI_OVERVIEW
Selects keywords whose SERP contains AI Overview.
serp_feature_filter=aio,0
ranks_with_serp_feature=AI_OVERVIEW with target_url
Selects keywords where the target ranks inside AI Overview. The domain index is replaced by the target_url of the request.
display_limit, display_offset
limit, offset
The default limit is 10, as in v3.

v4 replaces the v3 SERP feature codes for AI features with descriptive uppercase values:

v3 code
v4 value
Search engine
aio
AI_OVERVIEW
Google
aai
ASK_AI
Bing
aic
AI_CHAT
Bing
aim
AI_SUMMARY
Bing
ais
AI_STORIES
Bing

To exclude a feature, replace the - prefix in serp_feature_filter with the serp_features_exclude parameter.

Jump to Step 3. Update response handlingStep 3. Update response handling

v3 field
v4 field
What changed
Ph
keyword
The field has a descriptive name. It contains the keyword text.
Tg
tags
The field has a descriptive name. It lists the tags assigned to the keyword.
Dt
tracking_points
Values for each tracking date are grouped in tracking_points, instead of being keyed by URL mask.
Sf
tracking_points[].serp_page_features
SERP features present on the results page for the keyword and date.
Positions for each URL mask in Dt
tracking_points[].position
Each tracking point has the position of the selected target.

v4 also returns:

  • tracking_points[].serp_features, with the SERP feature blocks where the target ranks for the keyword and date.
  • meta, with the request parameters used, such as campaign_id, channel, base_date, and comparison_date, and the total number of rows in total.

Sample requests:

v3 request: your keywords that rank in AI Overview
Shell
curl "https://api.semrush.com/reports/v1/projects/CAMPAIGN_ID/tracking/?type=tracking_position_organic&key=YOUR_API_KEY&action=report&url=*.your-domain.com%2F*:*.your-competitor-domain.com%2F*&serp_feature_filter=aio,0"
v3 request: competitor keywords that rank in AI Overview
Shell
curl "https://api.semrush.com/reports/v1/projects/CAMPAIGN_ID/tracking/?type=tracking_position_organic&key=YOUR_API_KEY&action=report&url=*.your-domain.com%2F*:*.your-competitor-domain.com%2F*&serp_feature_filter=aio,1"
v4 requests
Shell
# Get campaign ID
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/position-tracking/v1/seo/campaigns?project_id=PROJECT_ID"
 
# Get dates with collected data
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/position-tracking/v1/seo/campaigns/CAMPAIGN_ID/tracking-points?date_from=2026-11-01&date_to=2026-11-10"
 
# Your keywords that rank in AI Overview
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/position-tracking/v1/seo/campaigns/CAMPAIGN_ID/reports/overview?channel=ORGANIC&base_date=2026-11-01&comparison_date=2026-11-10&target_url=*.your-domain.com%2F*&ranks_with_serp_feature=AI_OVERVIEW"
 
# Competitor keywords that rank in AI Overview
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/position-tracking/v1/seo/campaigns/CAMPAIGN_ID/reports/overview?channel=ORGANIC&base_date=2026-11-01&comparison_date=2026-11-10&target_url=*.your-competitor-domain.com%2F*&ranks_with_serp_feature=AI_OVERVIEW"

To get all campaign keywords that trigger AI Overview, regardless of who ranks in it, use serp_features=AI_OVERVIEW instead of ranks_with_serp_feature.

Each additional target_url is a separate request, so check API Unit consumption before migrating this workflow.

Use this example if your integration runs a Site Audit, waits for it to finish, and retrieves the pages with a specific issue. This example uses broken internal links.

In both versions, this use case takes three requests: start the audit, check its progress, and retrieve the issue report. The endpoints and the way they pass IDs differ.

Your v3 integration sends these requests:

  1. Run audit starts the audit and returns a snapshot_id: POST /reports/v1/projects/{ID}/siteaudit/launch.
  2. Get information about campaign returns the audit status: GET /reports/v1/projects/{ID}/siteaudit/info.
  3. Detailed report for issue returns the pages affected by the issue: GET /reports/v1/projects/{ID}/siteaudit/snapshot/{snapshotId}/issue/{issueId}. Broken internal links have issue ID 8.

In v4, replace them with these requests:

  1. Start Audit starts the audit and returns an audit_report_id: POST /apis/v4/site-audit/v1/campaigns/:campaign_id/start.
  2. Get Audit Progress returns the audit stage: GET /apis/v4/site-audit/v1/campaigns/:campaign_id/progress.
  3. Get Issue Report returns the occurrences of one issue type: GET /apis/v4/site-audit/v1/campaigns/:campaign_id/issues/:issue_type/overview.

What you need to change:

  1. Replace the {ID} project ID in the URL with campaign_id. In v4, the Site Audit campaign ID is the same as the project ID.
  2. Replace snapshot_id with audit_report_id. Start Audit returns 202 Accepted right away, and audit_report_id is the ID the report is published under after the audit finishes successfully.
  3. Replace the status check with a check of stage in Get Audit Progress. Poll the endpoint until stage is FINISHED or ERROR, and be prepared for stage values that aren’t listed in the reference.
  4. Replace the numeric issueId with the issue_type path parameter. For example, issue ID 8 becomes INTERNAL_LINK_BROKEN.
  5. Remove snapshot_id from the issue request. Get Issue Report always returns the latest successful audit. To confirm that the results come from the audit you started, compare meta.audit_report_id with the audit_report_id returned by Start Audit.
  6. Replace page with offset. limit defaults to 10, and can be up to 100.
  7. Pass your v4 API key in the Authorization header.
  8. Update your response parser:
    • Read occurrences from data. source_url, target_url, and page_id keep their names. v4 also returns page_title, discovered, occurrence_number, visibility, and info.
    • Read the total number of occurrences from meta.total_count instead of total.

Sample requests and responses:

v3 requests
Shell
# Run audit
curl -X POST "https://api.semrush.com/reports/v1/projects/PROJECT_ID/siteaudit/launch?key=YOUR_API_KEY"
 
# Check audit status
curl "https://api.semrush.com/reports/v1/projects/PROJECT_ID/siteaudit/info?key=YOUR_API_KEY"
 
# Get pages with broken internal links
curl "https://api.semrush.com/reports/v1/projects/PROJECT_ID/siteaudit/snapshot/SNAPSHOT_ID/issue/8?key=YOUR_API_KEY&page=1&limit=10"
v3 response to Run audit
JSON
{
    "snapshot_id": "54102d92e4b0f889a040c9c8"
}
v4 requests
Shell
# Start audit
curl -X POST -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/site-audit/v1/campaigns/PROJECT_ID/start"
 
# Check audit progress
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/site-audit/v1/campaigns/PROJECT_ID/progress"
 
# Get pages with broken internal links
curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/site-audit/v1/campaigns/PROJECT_ID/issues/INTERNAL_LINK_BROKEN/overview?offset=0&limit=10"
v4 response to Start Audit
JSON
{
    "meta": {
        "request_id": "4fb1773ec2a8d61a0407f464599f897c",
        "status_code": 202,
        "success": true
    },
    "data": {
        "audit_report_id": "6711d8a2c5e94b7f3a1e0c63"
    }
}
v4 response to Get Audit Progress
JSON
{
    "meta": {
        "request_id": "4fb1773ec2a8d61a0407f464599f897c",
        "status_code": 200,
        "success": true
    },
    "data": {
        "campaign_id": 1234567,
        "pages_crawled": 1250,
        "pages_limit": 20000,
        "precrawl_status": "NO_ERRORS",
        "resources_crawled": 3480,
        "resources_total": 9120,
        "stage": "RUNNING",
        "stoppable": true
    }
}

Last updated: November 13, 2026

Was this page helpful?