CSV API

Introduction

The ActBlue CSV API allows you to download a subset of the same CSVs you can download via the web UI in your ActBlue dashboard programmatically, via an HTTP API. It is a REST style API that returns JSON responses and uses standard HTTP status codes.

When to Use

We recommend using CSV reports as the source of truth for reporting and compliance purposes. You can download the same CSV reports from your dashboard, by going to the Downloads page. The API is designed for campaigns and organizations that want to retrieve fresh CSVs on a requent basis and allows them to automate the process of retrieving CSVs, without having to manually trigger downloads via the dashboard.

In addition to CSVs, ActBlue provides webhooks for notifying your system when a contribution is made, when it is refunded, and when a recurring contribution is cancelled. Documentation for our webhooks can be found here. Webhooks contain much of the same information as CSVs and we recommend using them for real-time data about contributions and for syncing data to third party integration partners listed here. However, CSVs will provide the most thorough and accurate data about your fundraising, which is why they should be used for compliance instead of using webhooks.

Authentication

the API Credentials option selected in the dashboard menu

The API uses Basic Authentication on all its endpoints: a username and password, separated by a colon, are encoded using Base64 and included in the HTTP ‘Authorization’ header, in the format Basic <encoded username and password>. We require SSL for all API requests to ensure that this authentication mechanism is secure.

You can generate credentials for the API in your dashboard. Click on the “API Credentials” link under “Admin”. When you generate a credential you will receive two values: a client UUID and client secret. Use the client UUID as your username and client secret as your password in the basic authentication header. These credentials only give access to the API; they will not allow you to log in to secure.actblue.com. Keep your client secret secure and treat it the way you would a password.

A credential only gives you access to data for the campaign or organization you generated it for - it will not give you access to any other campaign or organization's data, even if you have access to them through your ActBlue admin user account.

Usage

To download CSVs from the API, you will need to make requests to two different endpoints.

First, you’ll need to initiate the download via a POST request to the /api/v1/csvs endpoint. This request will return a JSON response that includes an ID. You’ll then use this ID to make a request to /api/v1/csvs/<id>. This endpoint returns the status of the CSV being generated, and when it is complete, a download URL. Since some CSVs may take several minutes to generate, you’ll need to poll that endpoint, repeatedly checking for updates until you get a result.

Once the CSV has finished generating, you can retrieve it from the provided download URL.

A generated report is cached for two hours, so if you retrieve the same report within two hours, you will not receive any new data.

Endpoints

All API endpoints start with https://secure.actblue.com/api/v1. They are both secured by Basic Authentication, so you will need to pass your credentials in the Authorization header each time (see Authentication for details.) There are currently two endpoints:

  • the Create CSV endpoint, which allows you to request that CSV be generated
  • the Get CSV endpoint, which allows you to check the status of the CSV you requested and provides the URL to download it from when it is done generating

Supported CSV Types

The following CSV types can be retrieved via the API:

  • paid_contributions: paid, non-refunded contributions to the campaign or organization you created the credential for. Equivalent to the 'Contributions over a specified time period' CSV on the Downloads page in your ActBlue dashboard.
  • refunded_contributions: contributions to the requesting campaign or organization that were refunded during the date range you specified.
  • managed_form_contributions: contributions made through any form that is managed by the requesting entity, including contributions to other entities on tandem forms.
  • cancelled_recurring_contributions: recurring contributions that were cancelled between the dates you selected.
The CSV type is specified as a parameter to the Create CSV endpoint described below.

Create CSV endpoint

URL: https://secure.actblue.com/api/v1/csvs

Method: POST

Successful Response Code: 202 (Accepted)

Example request body:

      {
        "csv_type": "paid_contributions",
        "date_range_start": "2020-01-01",
        "date_range_end": "2020-02-01",
      }
    

Example response body:

    {
      "id": "928759de-17a4-11eb-adc1-0242ac120002",
    }
    

Request Parameters

Parameter Description Format Nullable
csv_type Type of CSV you are requesting. See the 'Supported CSV Types' section above for more details. String, one of 'paid_contributions', 'refunded_contributions', 'cancelled_recurring_contributions' or 'managed_form_contributions'

Response Parameters

Parameter Description Format Nullable
id unique identifier of the CSV you requested String (UUID)

Get CSV endpoint

URL: https://secure.actblue.com/api/v1/csvs/<id>

Method: GET

Successful Response Code: 200 (OK)

Example request URL: https://secure.actblue.com/api/v1/csvs/928759de-17a4-11eb-adc1-0242ac120002 (requests should have no body contents)

Example response body:

      {
        "id": "928759de-17a4-11eb-adc1-0242ac120002",
        "download_url": "https://www.example.com/example.csv",
        "status": "complete"
      }
    

Request Parameters:

None - but the id you receive from the Create CSV endpoint must be included in the URL in this format: https://secure.actblue.com/api/v1/csvs/<id>

Response Parameters:

Parameter Description Format Nullable
id Unique identifier of the CSV you requested String (UUID)
download_url URL from which you can download the generated CSV, valid for 10 minutes after retrieval. Null until CSV has finished generating. Keep this URL secure because until it expires, it could be used by anyone to download the CSV. String (URL)
status Status of CSV generation String: either ‘in_progress’ or 'complete'

Errors

The API uses standard HTTP error codes to indicate whether a request has succeeded or failed. Codes in the 2XX range indicate success. Codes in the 4XX range indicate that the problem is on the requester’s end - for example the request was not authenticated, contained invalid parameters, or lacked required parameters. Codes in the 5XX range indicate there was a problem on our end and should be rare.

Requests that error will also have a response body with more details. Example:

    {
      errors: [
        {
          message: "date_range_start or date_range_end is invalid,
            please use a valid date with the format YYYY-MM-DD"
        }
      ]
    }
    

Rate Limiting

The create API endpoint has a rate limit of 10 successful requests per minute. If you go over this limit, you will receive a response with the code 429 (Too Many Requests) and will need to wait 10 minutes before making further requests.

We may change or adjust rate limits in the future as necessary, so make sure your code properly handles receiving 429 responses and slows down its rate of requests.

Versioning

Versioning is specified by the version in the URL you make requests to. Currently, we only have one version: 'v1'.

We will not release a new version when we make minor, non-breaking, changes such as adding a new property. Make sure your integration can handle additonal properties being added to responses. Specify the version you wish to use with the version in the URL: for example, https://secure.actblue.com/api/v1/csvs would specify that you want to use the version ‘v1’. Currently, we only have one version: 'v1'.

We will release a new version for any major, breaking, changes such as:

  • Changing a property name (e.g. from download_url to downloadUrl)
  • Changing a data type on a property (e.g. from an integer to a float)
  • Adding a required field on the request (e.g. a new required header or property in a request body)
  • Removing a property on the response (e.g. removing status)

ActBlue will notify API users in advance of any planned version deprecation or removal.

FAQs and Troubleshooting

Why am I receiving an error when downloading the CSV from the download URL I retrieved from the Get CSV endpoint?

  • You're including the basic authorization headers in the request to download the CSV: the CSV download URL is presigned, so you should not include the basic authorization headers you included for the other requests when making requests to the download URL.
  • You're attempting to use the URL after it has expired: the CSV download URL is only valid for 10 minutes after you retrieved it from the Get CSV endpoint. If you need to access it again after 10 minutes, you'll need to make another request to the Get CSV endpoint, which will return a new URL.

Why am I receiving a '404 not found' error when making requests to the Create CSV or Get CSV endpoints?

  • You're not using HTTPS: ensure that the URL your code is using for the endpoint begins with 'https://', not 'http://'
  • You're not using the correct HTTP request type: make sure that you are using a POST request for the Create CSV endpoint, and a GET request for the Get CSV endpoint.

If you have other questions not listed here, feel free to reach out to integrations@actbluetech.com for assistance.

Example Code

The following is an example Ruby script to help guide your implementation:

    require 'http'
    require 'date'
    require 'json'

    # Pre-requisites:
    # You'll need to have Ruby installed (https://www.ruby-lang.org/en/documentation/installation/)
    # and then run 'gem install http' before running this script
    # Example command to run script:
    # AB_CLIENT_UUID="example-uuid" AB_CLIENT_SECRET="example-secret" ruby csv_download_api_example.rb
    # (replace example-uuid and example-secret with your own values, and csv_download_api_example.rb
    # with filename where you saved this script)

    CLIENT_UUID = ENV['AB_CLIENT_UUID']
    # Treat your client secret like a password and never include it directly in your code
    CLIENT_SECRET = ENV['AB_CLIENT_SECRET']
    BASE_URI = 'https://secure.actblue.com/api/v1'

    # 1. Set up an HTTP client with basic authentication using the ActBlue client uuid and client secret
    client = HTTP.
      basic_auth(user: CLIENT_UUID, pass: CLIENT_SECRET).
      headers(accept: 'application/json')

    # 2. Make the Create CSV request to initiate the CSV generation
    body = {
      csv_type: 'paid_contributions',
      date_range_start: (Date.today - 31).to_s,
      date_range_end: (Date.today + 1).to_s,
    }
    response = client.post("#{BASE_URI}/csvs", json: body)
    unless response.status == 202
      raise "Failed to create CSV: #{response.body}, status: #{response.status}"
    end
    puts 'Initiated CSV generation successfully'

    # 3. Extract the the CSV ID from the response
    csv = JSON.parse(response.body)
    csv_id = csv['id']

    # 4. Poll the Get CSV endpoint to check whether the CSV has finished generating
    # which will be signified by a download_url being present on the response
    download_url = nil
    while download_url.nil?
      sleep(1) # wait briefly between each request to give CSV time to generate
      puts 'Polling for download URL, this may take a few minutes'
      response = client.get("#{BASE_URI}/csvs/#{csv_id}")
      unless response.status == 200
        raise "Polling for CSV failed: #{response.body}, status: #{response.status}"
      end
      csv = JSON.parse(response.body)
      download_url = csv['download_url']
    end

    # 5. Once we have a download URL, download the file from it
    puts 'Download URL retrieved, downloading CSV'
    filename = 'paid_contributions.csv'
    File.open(filename, 'wb') do |f|
      # use new HTTP client without basic auth headers since download_url is presigned
      response = HTTP.get(download_url)
      unless response.status == 200
        raise "Download of CSV failed, body: #{response.body}, status: #{response.status}"
      end
      # stream the response body to a file
      response.body.each do |chunk|
        f.write(chunk)
      end
    end

    puts "Successfully saved file to #{filename}"