• SDK Support
    Drop-in Components
    Authorization
    Root
    Accounts
    Customers
    Knowledge-based Authentication (KBA)
    Beneficial Owners
    Documents
    Exchanges
    Funding Sources
    Transfers
    Mass payments
    Labels
    Events
    Webhook subscriptions
    Webhooks

Introduction #

Welcome to the Dwolla API documentation. This API will give you the ability to connect your software to banking infrastructure to move money, store funds, validate customer identities, and verify bank accounts.

Making requests #

All requests should supply the Accept: application/vnd.dwolla.v1.hal+json header. POST requests must either specify the Content-Type: application/vnd.dwolla.v1.hal+json or Content-Type: application/json header. Request and response bodies are JSON encoded.

Requests must be made over HTTPS. Any non-secure requests are met with a redirect (HTTP 302) to the HTTPS equivalent URI.

bash
POST https://api.dwolla.com/customers
Content-Type: application/json
Accept: application/vnd.dwolla.v1.hal+json
Authorization: Bearer myOAuthAccessToken123

{
  "foo": "bar"
}

... or ...

GET https://api.dwolla.com/accounts/a84222d5-31d2-4290-9a96-089813ef96b3/transfers

Authentication #

All requests require either an OAuth access token or a client_id and client_secret in order to authenticate with the API. OAuth access tokens are passed via the Authorization HTTP header:

Authorization: Bearer {access_token_here}

API Host #

Production: https://api.dwolla.com

Sandbox: https://api-sandbox.dwolla.com

Rate Limits #

Dwolla imposes a rate limit for any applications that make requests to our API. Currently, there are two types of rate limits that we define:

  • Concurrency-based that is imposed for transfers that, when created, are sourced from a Dwolla Balance associated with a Dwolla Account or Customer. Applications that attempt to initiate transfers sourced from the same balance funding source in quick succession may receive an HTTP 429 Too Many Requests status code.

  • Volume-based that is imposed for all Dwolla endpoints. At this time, these thresholds are defined as outside the range of what we consider normal API usage. If the rate limit is reached for an endpoint, subsequent requests to the same endpoint will result in an HTTP 429 Too Many Requests status code. This rate limit will persist for 5 minutes.

Dwolla recommends building a mechanism into your application for 429 Too Many Requests responses, which would retry the request following an exponential backoff schedule to reduce request volume, and utilizes idempotency keys, where applicable. This ensures actions only perform once and prevents creation of duplicate records.

If you believe that your application will require a high rate of API calls, please contact support@dwolla.com for further assistance.

IP Allowlist #

IP allowlisting enables you to define IP addresses from which you want to allow access to the Dwolla API. This helps to prevent unauthorized networks from performing actions on behalf of your application.

Things to remember:

  • The IP Allowlist option is made available once an application has completed the application approval process.
  • If you are logged in as a sub-user, you will need Edit permissions for Applications to be able to edit the IP allowlist.

To set up IP allowlisting navigate to the Applications tab in the Dashboard. Locate your application for which you want to specify a list of IP addresses, then click on Allow List. You can then specify an IP address (e.g., 192.0.2.1) or a CIDR IP range (e.g., 192.0.2.1/24) and add a description for that entry.

Production - https://dashboard.dwolla.com/applications
Sandbox - https://dashboard-sandbox.dwolla.com/applications

Immediately after adding your first IP address, any attempt to make a call to the API from an IP address not in the list will result in a 403 Forbidden HTTP error code with the following response body:

bash
{
  "code": "InvalidIpAddress",
  "message": "Access to this resource is forbidden from this network location."
}

Idempotency key #

To prevent an operation from being performed more than once, Dwolla supports passing in an Idempotency-Key header with a unique key as the value. Multiple POSTs with the same idempotency key and request body won't result in multiple resources being created. It is recommended to use a random value for the idempotency key, like a UUID (i.e. - Idempotency-Key: d2adcbab-4e4e-430b-9181-ac9346be723a).

For example, if a request to initiate a transfer fails due to a network connection issue, you can reattempt the request with the same idempotency key to guarantee that only a single transfer is created.

If you reattempt a POST request with the same value for the Idempotency-Key, rather than creating new or potentially duplicate resources, you will receive a 201 Created, with the original response of the created resource. If the Dwolla server is still processing the original POST request, you will receive a 409 Conflict error response on the subsequent request. Multiple POSTs with the same idempotency key including an exact match request body won’t result in multiple resources being created. Idempotency keys are intended to prevent conflicts over a short period of time, therefore keys which are paired with a request body expire after 24 hours.

Example transfer using an Idempotency Key

JavaScript
var headers = {
  "Idempotency-Key": "19051a62-3403-11e6-ac61-9e71128cae77",
};
var requestBody = {
  _links: {
    source: {
      href: "https://api-sandbox.dwolla.com/funding-sources/04173e17-6398-4d36-a167-9d98c4b1f1c3",
    },
    destination: {
      href: "https://api-sandbox.dwolla.com/funding-sources/707177c3-bf15-4e7e-b37c-55c3898d9bf4",
    },
  },
  amount: {
    currency: "USD",
    value: "1.00",
  },
};

dwolla
  .post("transfers", requestBody, headers)
  .then((res) => res.headers.get("location")); // => 'https://api-sandbox.dwolla.com/transfers/74c9129b-d14a-e511-80da-0aa34a9b2388'

Errors #

Error responses use HTTP status codes to indicate the type of error. The JSON response body will contain a top-level error code and a message with a detailed description of the error. Errors will contain their own media type and will closely align with this spec.

Example HTTP 401 error #

bash
{
  "code": "InvalidAccessToken",
  "message": "Invalid access token."
}

Common errors #

The following errors are common across all API endpoints.

HTTP StatusError CodeDescription
400BadRequestThe request body contains bad syntax or is incomplete.
400ValidationErrorValidation error(s) present. See embedded errors list for more details. (See below)
401InvalidCredentialsMissing or invalid Authorization header.
401InvalidAccessTokenInvalid access token.
401ExpiredAccessTokenGenerate a new access token using your client credentials.
401InvalidAccountStatusInvalid access token account status.
401InvalidApplicationStatusInvalid application status.
401InvalidScopesMissing or invalid scopes for requested endpoint.
403ForbiddenThe supplied credentials are not authorized for this resource.
403InvalidResourceStateResource cannot be modified.
404NotFoundThe requested resource was not found.
405MethodNotAllowed(varies)
406InvalidVersionMissing or invalid API version.
500ServerErrorA server error occurred. Error ID: {ID}
500RequestTimeoutThe request timed out.

Validation errors #

Responses with a top-level error code of ValidationError are returned when it’s possible to correct a specific problem with your request. The response will include a message: "Validation error(s) present. See embedded errors list for more details." At least one, but possibly more, detailed error will be present in the list of embedded errors. Multiple errors are represented in a collection of embedded error objects.

_embedded JSON object

ParameterDescription
errorsAn array of JSON object(s) that contain a code, message, and path.

The path field is a JSON pointer to the specific field in the request that has a problem. The message is a human readable description of the problem. The code is a detailed error code that can have one of the following values:

CodeDescription
Required{field name} is required. For example, null or empty string in required field.
Invalid{field name} invalid.
InvalidFormat{field name} is not in a valid format. For example, characters in the amount field.
DuplicateDuplicate resource error. For example, A customer with the specified email already exists.
ReadOnlythis field is not allowed to be modified
NotAllowedvalue, while valid/exists, is not allowed to be used
Restrictedaccount or customer restricted from this activity
InsufficientFundsused on source or destination fields of transfer endpoint
RequiresFundingSourceused on destination field of transfer endpoint to indicate customer needs a bank
FileTooLargeused on document upload

Example HTTP 400 validation error

bash
{
    "code": "ValidationError",
    "message": "Validation error(s) present. See embedded errors list for more details.",
    "_embedded": {
        "errors": [
            {
                "code": "Required",
                "message": "FirstName required.",
                "path": "/firstName",
                "_links": {}
            }
        ]
    }
}

Relationships and available actions for a resource are represented with links. All resources have a _links attribute. At a minimum, all resources will have a self link which indicates the URL of the resource itself.

Some links, such as funding-sources, give you a URL which you can follow to access related resources. For example, the customer resource has a funding-sources link which, when followed, will list the customer's available funding sources.

Responses which contain a collection of resources have pagination links, first, next, last, and prev.

bash
{
  "_links": {
    "self": {
      "href": "https://api.dwolla.com/customers/132681FA-1B4D-4181-8FF2-619CA46235B1"
    },
    "funding-sources": {
      "href": "https://api.dwolla.com/customers/132681FA-1B4D-4181-8FF2-619CA46235B1/funding-sources"
    },
    "transfers": {
      "href": "https://api.dwolla.com/customers/132681FA-1B4D-4181-8FF2-619CA46235B1/transfers"
    },
    "retry-verification": {
      "href": "https://api.dwolla.com/customers/132681FA-1B4D-4181-8FF2-619CA46235B1"
    }
  },
  "id": "132681FA-1B4D-4181-8FF2-619CA46235B1",
  "firstName": "Jane",
  "lastName": "doe",
  "email": "jdoe@nomail.com",
  "type": "personal",
  "status": "retry",
  "created": "2015-09-29T19:47:28.920Z"
}

Tools #

The following section will outline development tools you can take advantage of to assist in your integration with the Dwolla API. The available tools can help to improve your testing and development workflow, as well as aid in solving a difficult problem (e.g. UI generation) when integrating Dwolla into your application.

Dwolla Hal-Forms #

Dwolla HAL-Forms is an extension of the HAL spec and was created to describe how Dwolla represents forms in the API. The extension starts with the media type. The media type should be used as a profile link as part of the Accept header of the request in conjunction with the Dwolla HAL style media type. By including these two media-type identifiers in the Accept header, the API knows that you’re looking for a form for the given resource.

Example Accept header value

application/vnd.dwolla.v1.hal+json; profile="https://github.com/dwolla/hal-forms"

The primary benefit is the ability to dynamically generate your UI based on the state of a particular resource. Your application can easily transition state without knowing Dwolla's business rules and what information needs to included in the actual request to transition state. When an "edit-form" link relation is returned on the resource, then your application can follow the link by making a GET request to that resource, including the header shown above. The response will include a simple JSON response body that contains information on the HTTP method, message content-type, and the request parameters used when sending the request to the Dwolla API. Note: Currently, forms are only returned for creating & editing customers, but we’re looking forward to expanding them across our existing and future endpoints.

Reference the spec for more information on the properties that can be returned in the Dwolla HAL-FORMS response. Or read a blog post from one of our developers on building out this functionality.

2022 All Rights Reserved
Financial institutions play an important role in our network.

All funds transfers made using the Dwolla Platform are performed by a financial institution partner, and any funds held in a Dwolla Balance are held by a financial institution partner. Learn more about our financial institution partners.