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.
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.
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
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}
Production: https://api.dwolla.com
Sandbox: https://api-sandbox.dwolla.com
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 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:
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:
{
"code": "InvalidIpAddress",
"message": "Access to this resource is forbidden from this network location."
}
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 POST
s 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.
POST https://api-sandbox.dwolla.com/transfers
Accept: application/vnd.dwolla.v1.hal+json
Content-Type: application/vnd.dwolla.v1.hal+json
Authorization: Bearer pBA9fVDBEyYZCEsLf/wKehyh1RTpzjUj5KzIRfDi0wKTii7DqY
Idempotency-Key: 19051a62-3403-11e6-ac61-9e71128cae77
{
"_links": {
"destination": {
"href": "https://api-sandbox.dwolla.com/funding-sources/04173e17-6398-4d36-a167-9d98c4b1f1c3"
},
"source": {
"href": "http://api-sandbox.dwolla.com/funding-sources/707177c3-bf15-4e7e-b37c-55c3898d9bf4"
}
},
"amount": {
"currency": "USD",
"value": "1337.00"
}
}
...
HTTP/1.1 201 Created
Location: https://api-sandbox.dwolla.com/transfers/74c9129b-d14a-e511-80da-0aa34a9b2388
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.
{
"code": "InvalidAccessToken",
"message": "Invalid access token."
}
The following errors are common across all API endpoints.
HTTP Status | Error Code | Description |
---|---|---|
400 | BadRequest | The request body contains bad syntax or is incomplete. |
400 | ValidationError | Validation error(s) present. See embedded errors list for more details. (See below) |
401 | InvalidCredentials | Missing or invalid Authorization header. |
401 | InvalidAccessToken | Invalid access token. |
401 | ExpiredAccessToken | Generate a new access token using your client credentials. |
401 | InvalidAccountStatus | Invalid access token account status. |
401 | InvalidApplicationStatus | Invalid application status. |
401 | InvalidScopes | Missing or invalid scopes for requested endpoint. |
403 | Forbidden | The supplied credentials are not authorized for this resource. |
403 | InvalidResourceState | Resource cannot be modified. |
404 | NotFound | The requested resource was not found. |
405 | MethodNotAllowed | (varies) |
406 | InvalidVersion | Missing or invalid API version. |
500 | ServerError | A server error occurred. Error ID: {ID} |
500 | RequestTimeout | The request timed out. |
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 objectParameter | Description |
---|---|
errors | An 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:
Code | Description |
---|---|
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. |
Duplicate | Duplicate resource error. For example, A customer with the specified email already exists. |
ReadOnly | this field is not allowed to be modified |
NotAllowed | value, while valid/exists, is not allowed to be used |
Restricted | account or customer restricted from this activity |
InsufficientFunds | used on source or destination fields of transfer endpoint |
RequiresFundingSource | used on destination field of transfer endpoint to indicate customer needs a bank |
FileTooLarge | used on document upload |
{
"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
.
{
"_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"
}
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 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.
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.
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.