Bulk Upload API

Overview

This API enables you to initiate a Consumer Append job using the REACH job processing queue. It takes an input CSV file of records, appends data (like email, phone, address, etc), and returns a downloadable enriched CSV file.

Authentication

All API requests must include a valid API key passed in the request headers. For more details please see Authentication

If your API key is missing, invalid, or expired, the API will return a 401 Unauthorized error.

API Workflow

  1. Upload a CSV File: make a POST API request to upload a file

    1. https://api.versium.com/v2/lists
    2. The JSON response will contain meta information about the list, including the “id” field, which will be used in the API request to start a job.
  2. Start a Job: make a POST API request to start the job

    1. https://api.versium.com/v2/jobs?operation=b2cContactAppend&sub_jobs[]=<sub_job>&input_list_id=<list-id>
    2. The JSON response will contain meta information about the job, including a status URL to send subsequent API requests to.
  3. Check Job Status: make a GET API request to get the job status

    1. https://api.versium.com/v2/jobs/<job-id>
    2. Once the job has completed creating the final, output csv file, this JSON response will contain an API endpoint to download the file.
  4. Download Output List: make a GET API request to download the complete CSV file

    1. https://api.versium.com/v2/lists/<list-id>/download
    2. The response will be a stream of JSON objects, one object per line

1. Upload a CSV File

Method: POST

Endpoint:https://api.versium.com/v2/lists

Headers:

  • Content-Type: multipart/form-data
  • x-versium-api-key: your API key

Required Config params

name

description

value type

possible values

list

The CSV file

CSV

has_header

A Boolean for whether or not the file contains a header row.

Boolean

1 or 0

header_map

A JSON objects that contains the mapping of columns indexes to know REACH input contact fields (see example below)

JSON object

REACH recognizes the following fields:

  • email

  • phone

  • first

  • last

  • address

  • city

  • state

  • zip

  • country

header_map example:

{
"email": 0,
"phone": 1,
"first": 2,
"last": 3,
"address": 4,
"city": 5,
"state": 6,
"zip": 7,
"country": 8
}

Example

Example: upload a list named consumer.csv, with header map of {"first":0,"last":1,"address":2,"city":3,"state":4}

Response Structure

Content-type: application/json

{
    "versium": {
        "version": "2.0",
        "query_id": "de87092719ed76f66ee16c375cb4bfbe",
        "query_time": 0.3544750213623047,
        "results": {
            "id": 953369,
            "guid": "56749382-9ebe-4a71-93ab-e93f37c761ea",
            "name": "consumer.csv",
            "campaign_id": null,
            "created_at": "2025-08-05T20:46:35.000000Z",
            "finished_at": null,
            "header_map": {
                "first": 0,
                "last": 1,
                "address": 2,
                "city": 3,
                "state": 4
            },
            "has_header": true,
            "delimiter_type": 1,
            "records": 199,
            "size": 9818,
            "input_field_fill_rate": {
                "first": 198,
                "last": 198,
                "address": 197,
                "city": 198,
                "state": 197
            },
            "column_count": 5,
            "append_field_fill_rate": null,
            "file_ready": true,
            "source": "API",
            "to_be_deleted": null,
            "last_download_date": null,
            "jobs": {
                "withTimestamps": false
            }
        }
    }
}

2. Start a Job

Method: POST

Endpoint: https://api.versium.com/v2/jobs?operation=b2cContactAppend&sub_jobs[]=<sub_job>&input_list_id=<list-id>


Required Config Params

name

description

value type

possibile values

notes

input_list_id

The id of the uploaded list to validate.

Integer

match_type

The strength of match to enforce for appended data.

string

indiv hhld

“indiv” requires first and last as inputs. ”hhld” requires last as an input.

operation

Which operation to perform. In this case, the value should be “b2cContactAppend”.

string

b2cContactAppend

sub_jobs[]

Which type of contact information to append.

array of strings

See the *sub_jobs[] options table below

You may provide multiple subjobs, but for improved accuracy and match rates, it is highly recommended to only select one at a time.

project_id

The Id of the project to place the output list into.

integer

A valid project Id for the account.

Not required if project_name is provided.

project_name

The name of the project to place the output list into. If the project doesn’t exist, it will be created.

string

Not required if project_id is provided.


sub_jobs[] options

valuenamedescription
b2cEmailAppendEmail AddressAdd an email address
b2cAddressAppendPostal AddressAdd a postal address
b2cPhoneAppendPrimary Phone NumberAdd a phone number (could be landline or mobile or voip)
b2cMobilePhoneAppendMobile Phone OnlyAdd a mobile phone number
b2cMultiplePhoneAppendMultiple Phone NumbersAdd multiple phone numbers
b2cMultiMobilePhoneAppendMultiple Mobile Only PhonesAdd multiple mobile phone numbers
b2cPhoneAppendHQVerified Primary Phone NumberAdd a phone number (could be landline or mobile or voip)
b2cMobilePhoneAppendHQVerified Mobile Phone OnlyAdd a mobile phone number
b2cMultiplePhoneAppendHQVerified Multiple Phone NumbersAdd multiple phone numbers
b2cMultiMobilePhoneAppendHQVerified Multiple Mobile Only PhonesAdd multiple mobile phone numbers

Optional Config Params

namedescriptionvalue typepossibile valuesnotes
callback_urlA URL to ping when the job has completed or failed.string
rcfg_suppression_idsA comma-separated list of suppression list Ids to apply to this job. By default, all suppression lists are applied.stringA comma-separated list of suppression list IdsYour suppression list Ids can be found under the settings section of the REACH app: https://app.versium.com/account/suppressions

Note: If a callback URL is provided in the Job Creation API request, when the job has completed or failed, a POST request will be made to that URL. The body of the request will contain a JSON object identical to the JSON object returned by the** Job Status** API.

Example

Example of API call to perform a b2cEmailAppend on input_list 953369, perform a individual match type and save the new appended list in the project name BulkAPI_test:

https://api.versium.com/v2/jobs?operation=b2cContactAppend&sub_jobs[]=b2cEmailAppend&input_list_id=953369&match_type=indiv&project_name=BulkAPI_Test

Response Structure

Content-type: application/json

{
    "versium": {
        "version": "2.0",
        "query_id": "a20049b1cd84a854494f35b11d2e9b8e",
        "query_time": 0.3439779281616211,
        "results": {
            "id": 1204129,
            "guid": "2c21f1a5-c42c-46b6-be2d-f13b3f334153",
            "state": "dispatched",
            "operation": "b2cContactAppend",
            "created_at": "2025-08-05T20:50:00.000000Z",
            "finished_at": null,
            "config": {
                "match_type": "indiv",
                "sub_jobs": [
                    "b2cEmailAppend"
                ]
            },
            "output_list": {
                "id": 953370,
                "download_url": null,
                "num_matches": 0,
                "num_records": 0,
                "project_id": 138866,
                "insights": null
            },
            "state_url": "https://api.versium.com/v2/jobs/1204129",
            "callback_url": null,
            "suppression_input_list_ids": null,
            "est_sec_remaining": null,
            "progress_percentage": 0
        }
    }
}

3. Check the Job Status

Method: GET

Endpoint: https://api.versium.com/v2/jobs/<job-id>

Example

Obtaining the status of the previous example:

https://api.versium.com/v2/jobs/1204129

Response Structure

Content-type: application/json

{
    "versium": {
        "version": "2.0",
        "query_id": "08789177c0db0e7f0b0cde17ee089ff9",
        "query_time": 0.21101999282836914,
        "results": {
            "id": 1204129,
            "guid": "2c21f1a5-c42c-46b6-be2d-f13b3f334153",
            "state": "done",
            "operation": "b2cContactAppend",
            "created_at": "2025-08-05T20:50:00.000000Z",
            "finished_at": "2025-08-05 20:50:45",
            "config": {
                "match_type": "indiv",
                "sub_jobs": [
                    "b2cEmailAppend"
                ],
                "sub_job_ids": [
                    1204130
                ]
            },
            "output_list": {
                "id": 953370,
                "download_url": "https://api.versium.com/v2/lists/953370/download",
                "num_matches": 55,
                "num_records": 199,
                "project_id": 138866,
                "insights": null
            },
            "state_url": "https://api.versium.com/v2/jobs/1204129",
            "callback_url": null,
            "suppression_input_list_ids": null,
            "est_sec_remaining": 0,
            "progress_percentage": 100
        }
    }
}

Note: When state is "done", the job has completed, and the download_url is available.


4. Download Output List

Method: GET

Endpoint: https://api.versium.com/v2/lists/\<list-id>/download

Response Structure

  • Upon success, returns a streamed CSV file.
  • First line: Header row.
  • Each subsequent row: Input fields + appended contact data.

Example

To download the completed list of the above example:

https://api.versium.com/v2/lists/953370/download


Error responses

When an error occurs, the response object will contain an “errors” property, which is a string of arrays.

{
  "versium": {
    "version":"2.0", 
    "match_counts":{},
    "num_matches":0,   
    "num_results":0,   
    "query_id":"48f9238a-ba98-4c45-97df-74f405c97527",   
    "query_time":7.340619087219238,   
    "results":[],
    "errors": []
  }
}

HTTP Status Codes

The api will attempt to return HTTP status codes for successful and failed requests. Use these codes to determine whether the request was successful. When an error code is returned, check the “errors” property in the response object for more details.

For more details, please see HTTP Status Codes