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:

  • Consistent Response Format: All responses follow a standard structure with success, data, and request_id

  • Better Error Handling: Typed errors with codes, messages, and documentation links

  • Improved Pagination: has_more field for easier pagination handling

  • RESTful Conventions: Proper HTTP methods (PATCH for partial updates) and resource naming

  • New Features: Team usage endpoints, improved sender profile management, and more

  • Quick Reference

    V1 EndpointV2 EndpointNotes

    POST /v1/contactPOST /v2/contactsV2 supports upsert by email
    GET /v1/contactsGET /v2/contactsV2 has improved pagination
    GET /v1/contact/:idGET /v2/contacts/:idSame functionality
    PUT /v1/contact/:idPATCH /v2/contacts/:idV2 uses PATCH for partial updates
    DELETE /v1/contact/:idDELETE /v2/contacts/:idSame functionality
    GET /v1/campaign/listGET /v2/campaignsV2 follows REST conventions
    PUT /v1/campaign/:idPATCH /v2/campaigns/:idV2 uses PATCH
    GET /v1/teamsGET /v2/teamsSame functionality
    POST /v1/teamPOST /v2/teamsV2 uses plural nouns
    GET /v1/team/:idGET /v2/teams/:idSame functionality
    PUT /v1/team/:idPATCH /v2/teams/:idV2 uses PATCH
    GET /v1/sendersGET /v2/sendersSame functionality
    PUT /v1/sender/:idPATCH /v2/senders/:idV2 uses PATCH
    GET /v1/sender-profilesGET /v2/sender-profilesSame functionality


    Response Format Changes

    V1 Response (Inconsistent)

    json
    // 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)

    json
    // 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:

    javascript
    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:

    javascript
    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:

    javascript
    // 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:

    javascript
    // 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:

    javascript
    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(); // Array

    V2:

    javascript
    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:

    javascript
    // 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:

    javascript
    // 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:

    V1 FieldV2 Field

    TeamIdteam_id (in responses)
    CampaignIdcampaign_id (in responses)
    createdAtcreated_at
    updatedAtupdated_at
    maxPerDaymax_per_day
    warmingStagewarming_stage

    Note: Request bodies still accept TeamId and CampaignId for compatibility.


    Pagination Changes

    V1 Pagination

    javascript
    // 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 more

    V2 Pagination

    javascript
    // 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

    javascript
    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

    javascript
    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

  • [ ] Update base URL from /v1 to /v2

  • [ ] Change PUT requests to PATCH for partial updates

  • [ ] Update endpoint paths (e.g., /campaign/list/campaigns)

  • [ ] Update response handling to destructure { success, data, request_id }

  • [ ] Update error handling to use new error object structure

  • [ ] Update pagination logic to use has_more

  • [ ] Test all API integrations in staging

  • [ ] Monitor error rates after deployment

  • Getting Help

    If you encounter issues during migration:

  • Check our API Reference for detailed endpoint documentation

  • Contact support at support@supersend.io

  • Join our Discord community for real-time help

  • Timeline

    DateMilestone

    NowV2 is available and recommended
    June 30, 2026V1 deprecation warnings in API responses
    December 31, 2026V1 sunset - endpoints will return errors

    Start your migration today to ensure a smooth transition!