Welcome to the Salesfly® REST API.


All API requests are made to and all requests are served over HTTPS.


API calls made over plain HTTP are not supported and will fail.


As we develop future versions of our API that are not backwards-compatible, we will leave the old version running and create a new url for the latest version. We will retain support for obsolete versions for a generous period of time and will send email notifications of any changes.

The current API version is v1. Future versions will be v2, v3, etc.


All requests to the API must be authenticated with an API key. You can submit the API key in the HTTP request header, or you can specify the access token as a HTTP URL query parameter.


If you do not have an API Key, you can easily generate one by heading over to the API settings page.

In the HTTP Authorization header:

Authorization: Bearer YOUR-API-KEY

In the URL

Add api_key=YOUR-API-KEY to the URL:


API requests without authentication will fail.


Salesfly uses conventional HTTP status response codes to indicate the success or failure of an API request. In general: Status codes in the 2XX range indicate success. Status codes in the 4XX range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.). Status codes in the 5XX range indicate an error with Salesfly's servers (these are rare).

The body of an error response:

  "status": 404,
  "success": false,
  "code": "err-ip-not-found",
  "message": "IP address not found"

status is the HTTP status code, success is true upon success and false if there was an error. message is a descriptive error message string, and finally code is the error code (see below for a list of error codes).

Error codes

Code Description
err-access-denied Access was denied to the API endpoint. Check your API key permissions or IP address restrictions.
err-account-suspended Your account has been suspended due to a payment problem.
err-bad-gateway Bad gateway (DNS or routing problem, 502).
err-date-before-2000 Date must be after January 1, 2000.
err-date-must-be-in-the-past Date must be in the past.
err-https-required You must use HTTPS to access the API.
err-internal-server-error Something went wrong on our side (500).
err-invalid-amount Amount must be a number larger than zero (ie. 12345.00).
err-invalid-apikey The API key provides was not valid (wrong format or not found in our database).
err-invalid-base-currency Invalid base currency.
err-invalid-date Invalid date (format must be YYYY-MM-DD).
err-invalid-dest-currency Invalid destination currency.
err-invalid-end-date Invalid end date (format must be YYYY-MM-DD).
err-invalid-ip You provided an invalid IP address for Geolocation lookup.
err-invalid-param The request has a missing or wrong input parameter.
err-invalid-request The request sent to the API server was incomplete or had invalid parameters.
err-invalid-sender Not allowed to send from this address.
err-invalid-source-currency Invalid source currency.
err-invalid-start-date Invalid start date (format must be YYYY-MM-DD) and must be after end date.
err-invalid-timespan Max timespan is one year (365 days).
err-ip-not-found The specified IP address was not found in the GeoIP database.
err-malware-detected Malware has been detected in outgoing mail.
err-missing-apikey You forgot to provide an API key.
err-missing-dkim Missing or invalid DKIM DNS record for sending domain.
err-missing-dmarc Missing or invalid DMARC DNS record for sending domain.
err-missing-spf Missing or invalid SPF DNS record for sending domain.
err-no-currency-data No currency data for chosen date.
err-no-data No data available.
err-no-recipients No valid mail recipients.
err-no-route Route not found.
err-not-modified Not modified (304)
err-pro-feature This feature is not available for your plan (upgrade to a paid plan to continue).
err-publishable-apikey This API call cannot be made with a publishable key.
err-rate-limit Too may requests - rate limit exceeded.
err-same-currency Source and destination currencies must be different.
err-service-unavailable Service unavailable (503).
err-spam-detected Outgoing mail has been flagged as spam.
err-too-many-recipients Too many mail recipients.
err-unexpected Unexpected response from server.
err-usage-exceeded You have exceeded your API usage limit.

Rate limits

API access rate limits are applied at a per-key basis in unit time. Access to the API using a key is limited to 60 requests per minute for the Lite plan, and 600 requests per minute for paid plans. In addition, every API response is accompanied by the following set of headers to identify the status of your consumption.

Header Description
X-RateLimit-Limit The maximum number of requests that the consumer is permitted to make per minute.
X-RateLimit-Remaining The number of requests remaining in the current rate limit window.
X-RateLimit-Reset The time at which the current rate limit window resets in UTC epoch seconds.
X-RateLimit-Delay The number of seconds until the rate counter is reset (only present when limit has been exceeded).

Once you hit the rate limit, you will receive a response similar to the following JSON, with a status code of 429.

  "status": 429,
  "success": false,
  "code": "err-rate-limit",
  "message": "Too may requests - rate limit exceeded"

Making requests

The API returns data in either JSON or XML format. JSON is the default format. You specify the format of the return data using the Accept header. You can also specify the data format using HTTP URL query parameter format. This is particulary useful for GET requests where you cannot set HTTP headers.

The Accept header:

Accept: application/json


Accept: application/xml

In the URL

Add format=json or format=xml to the URL:


POSTing data

For POST/PATCH/PUT requests you can upload data using JSON, XML, form URL encoded or multipart form data. You specify the type of content using the Content-Type header.


Content-Type: application/json
  "from": "",
  "to": ["", ""],
  "subject": "Test",
  "text": "This is a test"


Content-Type: application/xml

You must enclose an XML request inside a <request> tag.

	<text>This is a test</text>

Form URL encoded:

Content-Type: application/x-www-form-urlencoded

Multipart form data:

Content-Type: multipart/form-data; boundary="someboundary"


Single-item responses will be in this format:


  "status": 200,
  "success": true,
  "data": {
    "id": 1,
    "name": "test"

or XML:


Most endpoints return a single model of data.

Multi-item responses will be in this format:


  "status": 200,
  "success": true,
  "data": [
      "id": 1,
      "name": "test1"
      "id": 2,
      "name": "test2"

or XML:

       <data index="0">
       <data index="1">

NOTE: The data index starts from zero for XML arrays.

JSON Callbacks

The Salesfly API also supports JSONP callbacks. To use this feature, add callback=CALLBACK_FUNCTION to the HTTP request, and the result set will be returned as the callback function you specified.

Example request:

Example response:

  "data": {
    "country_code": "US"
  "status": 200,
  "success": true

ETags / Cache Control

The ETag or entity tag is part of the HTTP protocol. It is one of several mechanisms that HTTP provides for Web cache validation, which allows a client to make conditional requests. This allows caches to be more efficient and saves bandwidth, as a Web server does not need to send a full response if the content has not changed.

An ETag is an opaque identifier assigned by a web server to a specific version of a resource found at a URL. If the resource content at that URL ever changes, a new and different ETag is assigned. Used in this manner ETags are similar to fingerprints, and they can be quickly compared to determine if two versions of a resource are the same or not.

The Currency API supports ETags, and this allows you to check whether or not currency rates have changed since your last API request. If the rates have not been modified, your API response will be considerably smaller in size than if they have. Practically, ETags provide a mechanism to cache exchange rate data as long as it is not updated.

This is how you use it in your client code:

1. Save the latest API response

Each request to the Currency API will include an ETag and a Date in the HTTP response headers.

The Etag is a unique alphanumeric identifier for the data returned in the response, and the Date is the time at which the data was last modified. The date and time format is defined in RFC7231.


Date: Mon, 16 Mar 2020 10:15:46 GMT
ETag: "e33161ba2244ff74b9c9f1739cebec80"

2. Add the "If-None-Match" header

The next time you make a request to the same API URL, add the If-None-Match header, with the value set to the ETag you saved from the previous request. Remember to wrap the value in double quotation '"' marks.

You also need to send an If-Modified-Since header, which will be the Date value from the last successful request.

If continue to use the example above, your two request headers would look like this:

If-None-Match: "e33161ba2244ff74b9c9f1739cebec80"
If-Modified-Since: Mon, 16 Mar 2020 10:15:46 GMT

3. If not modified, use cached data

If the data have not been updated since your last request, the response status code will be 304 – Not Modified, and no data will be returned.

You can now safely use the cached API response from your previous successful request.

4. If changed, cache the new response

If the rates have been modified since your last request, the latest data will returned as usual, along with new ETag and Date headers.

Go back to step 1.


Although ETags help reduce bandwidth for your users, all API requests still count towards your monthly usage – even if the data has not changed since your last request.

Formatted output

By default the output from the Salesfly API is not formatted in any way. In order to improve readability you can specify that you want the output to be formatted and indented.

To enable this feature, add indented=true to the API request:


Indented output is larger than normal output and should only be used for debugging purposes.

Your use and access to the API is expressly conditioned on your compliance with the policies, restrictions, and other provisions related to the API set forth in our Terms of Service and the Privacy Policy, in all uses of the API. If we believes that you have or attempted to violate any term, condition, or the spirit of these policies or agreements, your right to access and use the API may be temporarily or permanently revoked.

Salesfly is a registered trademark of UAB Salesfly.