## Making Requests

To interact with the Dwolla API, all requests must include the `Accept` header:

- `Accept: application/vnd.dwolla.v1.hal+json`

For POST requests, specify either of the following `Content-Type`:

- `Content-Type: application/vnd.dwolla.v1.hal+json`
- `Content-Type: application/json`

All request and response bodies are JSON encoded. Requests must be made over HTTPS. Any non-secure requests will be redirected (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
```

## API Host

| Environment | Base URL |
| --- | --- |
| Production | `https://api.dwolla.com` |
| Sandbox | `https://api-sandbox.dwolla.com` |

## Authentication

Dwolla uses the [OAuth 2 protocol](https://oauth.net/2/) to authorize API requests. Every call to the Dwolla API must include a valid access token in the `Authorization` header: `Authorization: Bearer {access_token}` Want to get up and running fast? The [Quickstart](https://developers.dwolla.com/docs/quickstart) walks through token generation and your first API call in under 5 minutes. This page covers the concepts in depth.

### Creating an application

Before requesting an access token, register an application with Dwolla by logging in to the [Dashboard](https://dashboard-sandbox.dwolla.com/) and navigating to the applications page. Each application has a `client_id` and `client_secret` (together, your client credentials) that identify it to the Dwolla API. The Sandbox creates an application automatically when you sign up — see the [Sandbox guide](https://developers.dwolla.com/docs/testing) for details.

Your `client_secret` should be kept a secret. Store client credentials securely and never expose them on the client side of your application.

### Dwolla’s authorization flow

OAuth 2 defines four main authorization grant types. Dwolla implements one: **Application authorization** — using the [client credentials grant](https://tools.ietf.org/html/rfc6749#section-4.4), your application obtains authorization to interact with the API on its own behalf. This is a server-to-server flow, also known as 2-legged OAuth.

### Requesting an access token

To obtain an access token, send a `POST` to `/token` with an HTTP Basic `Authorization` header containing your Base64-encoded client credentials. `Authorization: Basic Base64(client_id:client_secret)` The request body must be form-encoded and include `grant_type=client_credentials`:

| Parameter | Required | Type | Description |
| --- | --- | --- | --- |
| client_id | yes | string | Application key. Find it on the [applications page](https://dashboard-sandbox.dwolla.com/applications-legacy) of the Sandbox dashboard (or production dashboard). |
| client_secret | yes | string | Application secret. Available alongside the `client_id` on the applications page. |
| grant_type | yes | string | Must be set to `client_credentials`. |

For the full endpoint specification — request/response schema, error codes, and an interactive playground — see the [Create an application access token](https://developers.dwolla.com/docs/api-reference/tokens/create-an-application-access-token) reference.

```bash
curl -X POST 'https://api-sandbox.dwolla.com/token' \
  -H "Authorization: Basic $(echo -n 'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET' | base64)" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials'
```

```typescript
// Using dwolla — https://github.com/Dwolla/dwolla-typescript
import { Dwolla } from "dwolla";

const dwolla = new Dwolla({
  security: {
    clientID: process.env.DWOLLA_CLIENT_ID ?? "",
    clientSecret: process.env.DWOLLA_CLIENT_SECRET ?? "",
  },
  server: "sandbox",
});
// The SDK requests and caches tokens for you on the first API call.
```

```python
# Using dwollav2 — https://github.com/Dwolla/dwolla-v2-python
import dwollav2

client = dwollav2.Client(
  key=os.environ["DWOLLA_APP_KEY"],
  secret=os.environ["DWOLLA_APP_SECRET"],
  environment="sandbox",
)
app_token = client.Auth.client()
```

```ruby
# Using dwolla-v2-ruby — https://github.com/Dwolla/dwolla-v2-ruby
$dwolla = DwollaV2::Client.new(
  key: ENV['DWOLLA_APP_KEY'],
  secret: ENV['DWOLLA_APP_SECRET']
) do |config|
  config.environment = :sandbox
end
app_token = $dwolla.auths.client
```

```php
<?php
// Using dwolla-php — https://github.com/Dwolla/dwolla-php
use Dwolla;
use Dwolla\Models\Components;

$sdk = Dwolla\Dwolla::builder()
    ->setSecurity(
        new Components\Security(
            clientID: getenv('DWOLLA_CLIENT_ID'),
            clientSecret: getenv('DWOLLA_CLIENT_SECRET'),
        )
    )
    ->setServer('sandbox')
    ->build();
// The SDK requests and caches tokens for you on the first API call.
?>
```

### Token lifetime and refresh

Application access tokens expire one hour after they’re issued and are not paired with a refresh token. To continue making API calls, exchange your client credentials for a new token using the same request shown above. Official [Dwolla SDKs](https://developers.dwolla.com/docs/sdks-tools) handle token acquisition, caching, and renewal automatically — you only need to supply your `client_id` and `client_secret` at client initialization.

### Using an access token

Pass the token as a Bearer credential on every authenticated request:

```
POST https://api.dwolla.com/webhook-subscriptions
Content-Type: application/json
Accept: application/vnd.dwolla.v1.hal+json
Authorization: Bearer myApplicationAccessToken

{
  "url": "https://myapplication.com/webhooks",
  "secret": "sshhhhhh"
}

... or ...

GET https://api.dwolla.com/accounts/a84222d5-31d2-4290-9a96-089813ef96b3/transfers
Accept: application/vnd.dwolla.v1.hal+json
Authorization: Bearer myApplicationAccessToken
```

If the token is expired or invalid, Dwolla returns HTTP `401` with an `InvalidAccessToken` or `ExpiredAccessToken` error code. Catch these responses, request a fresh token, and retry the original call.
