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:
- List the
v3methods your application uses in each of the Projects API groups: project management, Position Tracking, and Site Audit. - Prepare a test environment where you can compare
v3andv4results.
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.
- Create a v4 API key.
- Configure the required permissions and optionally set an expiration date for added security.
- Store the API key securely.
- Update your integration to use the new key.
Pass your API key in the Authorization header:
Authorization: Apikey YOUR_API_KEYFor more information, refer to API v4 authorization.
Jump to Step 2. Find corresponding v4 endpointsStep 2. Find corresponding v4 endpoints
/apis/v4/projects/v1/projects/apis/v4/position-tracking/v1/seo/campaigns/apis/v4/site-audit/v1/campaignsTo identify the correct replacement:
- Find the
v3method in the v3 and v4 comparison reference. Look in the Project management, Position Tracking, and Site Audit sections. - Identify the equivalent
v4endpoint or endpoints. - Check if reproducing the same result requires multiple
v4requests.
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_idpath parameter. - Position Tracking campaign ID. Campaign-level methods take it as the
campaign_idpath 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:
filterbecomesscope, andurlbecomesdomain. Thev4List Projects method also supportslimitandoffsetfor pagination. - Position Tracking:
channelselects organic or paid data, and dates use theYYYY-MM-DDformat instead ofYYYYMMDD. Each report request takes onetarget_url. - Site Audit:
snapshot_idbecomesaudit_report_id, numeric issue IDs becomeissue_typevalues, and crawl settings are nested insettings.
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. permissioncodes become apermissionsobject 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.
- Confirm that your
v4API key has the necessary permissions. - Check that your application can call the
v4endpoints. - Make sure your application correctly processes
v4responses. - Confirm that
v4returns the data your use cases require, for the same projects and campaigns. - Verify that multi-request workflows retrieve and process all required data.
- 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.
- Make sure your integration handles
v4errors 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:
- Switch the verified operations from
v3tov4. - Monitor the integration for errors and unexpected results.
- Check API Unit consumption.
- Continue migrating any remaining supported
v3methods. - 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
v3filter withv4filter parameters and one request per target. - Replacing a sequence of
v3requests with thev4workflow.
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:
GET /management/v1/projectsIn v4, use the List Projects endpoint:
GET /apis/v4/projects/v1/projectsWhat you need to change:
- Replace the
v3endpoint with thev4List Projects endpoint. - Replace
filterwithscope, and change its values to uppercase. For example,filter=allbecomesscope=ALL. - Pass your
v4API key in theAuthorizationheader. - If you have many projects, use pagination.
limitdefaults to100and can be up to1000. Useoffsetto skip projects.meta.total_countreturns the total number of projects matching the scope. - Update your response parser:
- Read the list of projects from
data. - If your application reads the project domain from
url, update it to readdomain. - If your application checks
permissioncodes, update it to read the Boolean fields in thepermissionsobject:read,edit,delete,share, anddowngraded. - If your application reads the tool identifier from
tools[].tool, update it to readtools[].name.
- Read the list of projects from
Sample requests and responses:
curl "https://api.semrush.com/management/v1/projects?key=YOUR_API_KEY&filter=all"[
{
"url": "mysite.com",
"domain_unicode": "mysite.com",
"tools": [
{
"tool": "tracking"
}
],
"project_id": 643526670283248,
"project_name": "myproject",
"owner_id": 123456780,
"permission": [
"OWNER"
]
}
]curl -H 'Authorization: Apikey YOUR_API_KEY' "https://api.semrush.com/apis/v4/projects/v1/projects?scope=ALL&limit=100&offset=0"{
"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:
GET /reports/v1/projects/{campaignID}/tracking/?type=tracking_position_organicIn v4, use the Get Seo Overview endpoint:
GET /apis/v4/position-tracking/v1/seo/campaigns/:campaign_id/reports/overviewIn 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:
- Get the
campaign_idof your campaign with List Project Campaigns. - Get the dates with collected data with Get Campaign Tracking Points.
- Choose
base_dateandcomparison_datefrom the returned dates.
Jump to Step 2. Update request parametersStep 2. Update request parameters
type=tracking_position_organicchannel=ORGANICtype. channel is required.url with several domains separated by :target_urltarget_url to use the campaign target.date_begin, date_endbase_date, comparison_dateYYYYMMDD to YYYY-MM-DD. Both parameters are required.serp_feature_filter=aioserp_features=AI_OVERVIEWserp_feature_filter=aio,0ranks_with_serp_feature=AI_OVERVIEW with target_urltarget_url of the request.display_limit, display_offsetlimit, offsetlimit is 10, as in v3.v4 replaces the v3 SERP feature codes for AI features with descriptive uppercase values:
aioAI_OVERVIEWaaiASK_AIaicAI_CHATaimAI_SUMMARYaisAI_STORIESTo 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
PhkeywordTgtagsDttracking_pointstracking_points, instead of being keyed by URL mask.Sftracking_points[].serp_page_featuresDttracking_points[].positionv4 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 ascampaign_id,channel,base_date, andcomparison_date, and the total number of rows intotal.
Sample requests:
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"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"# 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.
Jump to Example 3. Migrate an audit run and broken internal links report (Site Audit)Example 3. Migrate an audit run and broken internal links report (Site Audit)
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:
- Run audit starts the audit and returns a
snapshot_id:POST /reports/v1/projects/{ID}/siteaudit/launch. - Get information about campaign returns the audit
status:GET /reports/v1/projects/{ID}/siteaudit/info. - 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 ID8.
In v4, replace them with these requests:
- Start Audit starts the audit and returns an
audit_report_id:POST /apis/v4/site-audit/v1/campaigns/:campaign_id/start. - Get Audit Progress returns the audit
stage:GET /apis/v4/site-audit/v1/campaigns/:campaign_id/progress. - 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:
- Replace the
{ID}project ID in the URL withcampaign_id. Inv4, the Site Audit campaign ID is the same as the project ID. - Replace
snapshot_idwithaudit_report_id. Start Audit returns202 Acceptedright away, andaudit_report_idis the ID the report is published under after the audit finishes successfully. - Replace the
statuscheck with a check ofstagein Get Audit Progress. Poll the endpoint untilstageisFINISHEDorERROR, and be prepared for stage values that aren’t listed in the reference. - Replace the numeric
issueIdwith theissue_typepath parameter. For example, issue ID8becomesINTERNAL_LINK_BROKEN. - Remove
snapshot_idfrom the issue request. Get Issue Report always returns the latest successful audit. To confirm that the results come from the audit you started, comparemeta.audit_report_idwith theaudit_report_idreturned by Start Audit. - Replace
pagewithoffset.limitdefaults to10, and can be up to100. - Pass your
v4API key in theAuthorizationheader. - Update your response parser:
- Read occurrences from
data.source_url,target_url, andpage_idkeep their names.v4also returnspage_title,discovered,occurrence_number,visibility, andinfo. - Read the total number of occurrences from
meta.total_countinstead oftotal.
- Read occurrences from
Sample requests and responses:
# 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"{
"snapshot_id": "54102d92e4b0f889a040c9c8"
}# 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"{
"meta": {
"request_id": "4fb1773ec2a8d61a0407f464599f897c",
"status_code": 202,
"success": true
},
"data": {
"audit_report_id": "6711d8a2c5e94b7f3a1e0c63"
}
}{
"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