V1 to V2 Migration Guide
Complete guide for migrating from SuperSend API V1 to V2
V1 to V2 Migration Guide
This guide helps you migrate from SuperSend API V1 to V2. V1 is deprecated and will be sunset on December 31, 2026.
Why Migrate?
V2 brings significant improvements:
success, data, and request_idhas_more field for easier pagination handlingQuick Reference
POST /v1/contactPOST /v2/contactsGET /v1/contactsGET /v2/contactsGET /v1/contact/:idGET /v2/contacts/:idPUT /v1/contact/:idPATCH /v2/contacts/:idDELETE /v1/contact/:idDELETE /v2/contacts/:idGET /v1/campaign/listGET /v2/campaignsPUT /v1/campaign/:idPATCH /v2/campaigns/:idGET /v1/teamsGET /v2/teamsPOST /v1/teamPOST /v2/teamsGET /v1/team/:idGET /v2/teams/:idPUT /v1/team/:idPATCH /v2/teams/:idGET /v1/sendersGET /v2/sendersPUT /v1/sender/:idPATCH /v2/senders/:idGET /v1/sender-profilesGET /v2/sender-profilesResponse Format Changes
V1 Response (Inconsistent)
// Success - varies by endpoint
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "john@example.com",
"first_name": "John"
}// Error - varies by endpoint
{
"error": "Contact not found"
}
V2 Response (Consistent)
// Success - always the same structure
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "john@example.com",
"first_name": "John"
},
"request_id": "req_abc123def456"
}// Error - always the same structure
{
"success": false,
"error": {
"type": "not_found_error",
"code": "contact_not_found",
"message": "Contact not found",
"doc_url": "https://docs.supersend.io/errors#contact_not_found"
},
"request_id": "req_abc123def456"
}
Detailed Migration Examples
Contacts
Create Contact
V1:
const response = await fetch('https://api.supersend.io/v1/contact', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'john@example.com',
first_name: 'John',
TeamId: 'team-uuid',
CampaignId: 'campaign-uuid'
})
});
const contact = await response.json();V2:
const response = await fetch('https://api.supersend.io/v2/contacts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'john@example.com',
first_name: 'John',
TeamId: 'team-uuid',
CampaignId: 'campaign-uuid'
})
});
const { success, data: contact } = await response.json();Update Contact
V1:
// V1 uses PUT for updates
const response = await fetch('https://api.supersend.io/v1/contact/contact-uuid', {
method: 'PUT',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
first_name: 'Johnny',
company: 'New Company'
})
});V2:
// V2 uses PATCH for partial updates
const response = await fetch('https://api.supersend.io/v2/contacts/contact-uuid', {
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
first_name: 'Johnny',
company: 'New Company'
})
});
const { success, data: contact } = await response.json();Campaigns
List Campaigns
V1:
const response = await fetch('https://api.supersend.io/v1/campaign/list?TeamId=team-uuid', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const campaigns = await response.json(); // ArrayV2:
const response = await fetch('https://api.supersend.io/v2/campaigns?TeamId=team-uuid', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const { success, data: campaigns, pagination } = await response.json();
// campaigns is an array
// pagination contains { limit, offset, total, has_more }Teams
Create Team
V1:
// V1 uses singular noun
const response = await fetch('https://api.supersend.io/v1/team', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'My Team' })
});V2:
// V2 uses plural noun
const response = await fetch('https://api.supersend.io/v2/teams', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'My Team' })
});
const { success, data: team } = await response.json();Field Name Changes
V2 uses snake_case consistently for all field names:
TeamIdteam_id (in responses)CampaignIdcampaign_id (in responses)createdAtcreated_atupdatedAtupdated_atmaxPerDaymax_per_daywarmingStagewarming_stageNote: Request bodies still accept TeamId and CampaignId for compatibility.
Pagination Changes
V1 Pagination
// V1 - must manually check if there are more results
const response = await fetch('/v1/contacts?limit=50&offset=0');
const contacts = await response.json();
// You had to fetch again to see if there are moreV2 Pagination
// V2 - includes has_more for easy pagination
const response = await fetch('/v2/contacts?limit=50&offset=0');
const { data, pagination } = await response.json();
// pagination: { limit: 50, offset: 0, total: 150, has_more: true }// Easy pagination loop
let offset = 0;
let hasMore = true;
while (hasMore) {
const { data, pagination } = await fetchContacts(offset);
processContacts(data);
hasMore = pagination.has_more;
offset += pagination.limit;
}
Error Handling
V1 Error Handling
try {
const response = await fetch('/v1/contact/invalid-id');
const data = await response.json();
if (data.error) {
console.error(data.error); // "Contact not found" (string)
}
} catch (err) {
console.error('Network error');
}V2 Error Handling
try {
const response = await fetch('/v2/contacts/invalid-id');
const { success, error, request_id } = await response.json();
if (!success) {
console.error([${request_id}] ${error.code}: ${error.message});
// [req_abc123] contact_not_found: Contact not found
// Error object includes:
// - type: 'not_found_error' 'invalid_request_error' etc.
// - code: 'contact_not_found'
// - message: 'Contact not found'
// - doc_url: 'https://docs.supersend.io/errors#contact_not_found'
// - param: (optional) which parameter caused the error
}
} catch (err) {
console.error('Network error');
}Migration Checklist
/v1 to /v2PUT requests to PATCH for partial updates/campaign/list → /campaigns){ success, data, request_id }has_moreGetting Help
If you encounter issues during migration:
Timeline
Start your migration today to ensure a smooth transition!