# 

## Prerequisites

* A valid API key — see [Obtain API credentials](/docs/how-tos/setup/obtain-credentials)
* A processor integration configured for ACH (Vericheck)


## Step 1: Build the request

Set `type` to `payment` and include the person's bank account details.

| Field | Required | Description |
|  --- | --- | --- |
| `type` | Yes | `payment` |
| `amount` | Yes | Amount in cents |
| `payment_method.type` | Yes | `ach` |
| `payment_method.account_number` | Yes | Bank account number |
| `payment_method.routing_number` | Yes | 9-digit ABA routing number |
| `payment_method.account_type` | Yes | `checking` or `savings` |
| `payment_method.name` | Yes | Account holder name |
| `payment_method.email` | Yes | Account holder email |
| `recurring` | Yes | `true` for recurring debits (PPD); `false` for one-time (WEB) |


## Step 2: Send the request

curl
```shell
curl -X POST \
  https://api.dev.paradisegateway.net/v1/transactions \
  -H "Content-Type: application/json" \
  -H "APIKEY: YOUR-API-KEY" \
  -d '{
    "type": "payment",
    "amount": 50000,
    "payment_method": {
      "type": "ach",
      "account_number": "9876543210",
      "routing_number": "021000021",
      "account_type": "checking",
      "name": "Montgomery Scott",
      "email": "scotty@example.com"
    },
    "recurring": false,
    "purchase_description": "Dilithium crystals"
  }'
```

Python
```python
import requests

resp = requests.post(
    "https://api.dev.paradisegateway.net/v1/transactions",
    headers={"Content-Type": "application/json", "APIKEY": "YOUR-API-KEY"},
    json={
        "type": "payment",
        "amount": 50000,
        "payment_method": {
            "type": "ach",
            "account_number": "9876543210",
            "routing_number": "021000021",
            "account_type": "checking",
            "name": "Montgomery Scott",
            "email": "scotty@example.com",
        },
        "recurring": False,
        "purchase_description": "Dilithium crystals",
    },
)
print(resp.json())
```

JavaScript
```javascript
const resp = await fetch(
  "https://api.dev.paradisegateway.net/v1/transactions",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "APIKEY": "YOUR-API-KEY",
    },
    body: JSON.stringify({
      type: "payment",
      amount: 50000,
      payment_method: {
        type: "ach",
        account_number: "9876543210",
        routing_number: "021000021",
        account_type: "checking",
        name: "Montgomery Scott",
        email: "scotty@example.com",
      },
      recurring: false,
      purchase_description: "Dilithium crystals",
    }),
  }
);
console.log(await resp.json());
```

C#
```csharp
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("APIKEY", "YOUR-API-KEY");

var payload = new
{
    type = "payment", amount = 50000,
    payment_method = new
    {
        type = "ach", account_number = "9876543210",
        routing_number = "021000021", account_type = "checking",
        name = "Montgomery Scott", email = "scotty@example.com"
    },
    recurring = false, purchase_description = "Dilithium crystals"
};
var resp = await client.PostAsJsonAsync(
    "https://api.dev.paradisegateway.net/v1/transactions", payload);
Console.WriteLine(await resp.Content.ReadAsStringAsync());
```

Java
```java
HttpClient client = HttpClient.newHttpClient();
String body = """
    {
      "type": "payment", "amount": 50000,
      "payment_method": {
        "type": "ach", "account_number": "9876543210",
        "routing_number": "021000021", "account_type": "checking",
        "name": "Montgomery Scott", "email": "scotty@example.com"
      },
      "recurring": false, "purchase_description": "Dilithium crystals"
    }
    """;
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.dev.paradisegateway.net/v1/transactions"))
    .header("Content-Type", "application/json")
    .header("APIKEY", "YOUR-API-KEY")
    .POST(HttpRequest.BodyPublishers.ofString(body)).build();
HttpResponse<String> resp = client.send(request,
    HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
```

Go
```go
payload := strings.NewReader(`{
  "type": "payment", "amount": 50000,
  "payment_method": {
    "type": "ach", "account_number": "9876543210",
    "routing_number": "021000021", "account_type": "checking",
    "name": "Montgomery Scott", "email": "scotty@example.com"
  },
  "recurring": false, "purchase_description": "Dilithium crystals"
}`)
req, _ := http.NewRequest("POST",
    "https://api.dev.paradisegateway.net/v1/transactions", payload)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("APIKEY", "YOUR-API-KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
```

PHP
```php
$ch = curl_init("https://api.dev.paradisegateway.net/v1/transactions");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ["Content-Type: application/json", "APIKEY: YOUR-API-KEY"],
    CURLOPT_POSTFIELDS => json_encode([
        "type" => "payment", "amount" => 50000,
        "payment_method" => [
            "type" => "ach", "account_number" => "9876543210",
            "routing_number" => "021000021", "account_type" => "checking",
            "name" => "Montgomery Scott", "email" => "scotty@example.com",
        ],
        "recurring" => false, "purchase_description" => "Dilithium crystals",
    ]),
]);
echo curl_exec($ch); curl_close($ch);
```

Ruby
```ruby
require "net/http"; require "json"
uri = URI("https://api.dev.paradisegateway.net/v1/transactions")
req = Net::HTTP::Post.new(uri, {
  "Content-Type" => "application/json", "APIKEY" => "YOUR-API-KEY",
})
req.body = {
  type: "payment", amount: 50000,
  payment_method: {
    type: "ach", account_number: "9876543210",
    routing_number: "021000021", account_type: "checking",
    name: "Montgomery Scott", email: "scotty@example.com",
  },
  recurring: false, purchase_description: "Dilithium crystals",
}.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts resp.body
```

## Step 3: Handle the response

```json
{
  "id": "TRANSACTION-03LPSC0TTY9ZXQ5MV0H4Y6W8A",
  "object": "CreateTransactionResponse",
  "type": "payment",
  "transaction_state": "authorized",
  "response_status": "Approved",
  "response_code": "00",
  "response_message": "The API request is approved.",
  "amount_requested": 50000,
  "amount_authorized": 50000,
  "amount": 50000,
  "correlation_id": "c3d4e5f6-a7b8-9012-cdef-123456789abc"
}
```

authorized ≠ settled
An `authorized` ACH transaction means the request was accepted. Funds settle in 2–3 business days and returns can occur for up to 60 days. Do not treat the initial response as final settlement.

## Step 4: Monitor for returns

ACH transactions can be returned after settlement. Poll `GET /v1/transactions/{id}` or configure webhooks to detect returns.

| Return code | Reason | Timeline |
|  --- | --- | --- |
| R01 | Insufficient funds | 2 business days |
| R02 | Account closed | 2 business days |
| R03 | No account / unable to locate | 2 business days |
| R10 | Customer advises not authorized | Up to 60 days |


For the full return code list, see [About ACH/bank account payments](/docs/concepts/transactions/ach-accounts).

## Next steps

* [Process an ACH payout](/docs/how-tos/process-payments/process-ach-payout) — send funds to a bank account
* [Process a payment with a stored token](/docs/how-tos/process-payments/process-payment-with-token) — use a tokenized bank account
* [About ACH/bank account payments](/docs/concepts/transactions/ach-accounts)