> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cleo-pay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Payment — POST /v1/payments API Reference

> POST /v1/payments sends an ACH payment against a payable or directly to a contact. Supports scheduling, partial amounts, and clearing speeds.

Use this endpoint to initiate an ACH payment. You can pay against an existing payable or send a payment directly to a contact by providing a `contactId`. Payments support optional scheduling, partial amounts, and accelerated clearing speeds.

<Warning>
  Exactly one of `payableId` or `contactId` is required per request. Providing both or neither will result in a validation error.
</Warning>

## Base URL

```
POST https://api.cleo-pay.com/v1/payments
```

## Authentication

All requests must include a Bearer token in the `Authorization` header.

```http theme={null}
Authorization: Bearer <token>
```

## Request Body

<ParamField body="payableId" type="string">
  The ID of an existing payable to pay. Use this when paying against a specific invoice or bill. Mutually exclusive with `contactId` — provide exactly one.
</ParamField>

<ParamField body="contactId" type="string">
  The ID of a contact to pay directly, without a pre-existing payable. A payable is automatically generated. Mutually exclusive with `payableId` — provide exactly one.
</ParamField>

<ParamField body="amountCents" type="number">
  Payment amount in US cents. Must be at least `1`.

  * When using `contactId`: **required**.
  * When using `payableId`: optional. Defaults to the remaining unpaid balance on the payable. You may specify a partial amount to make a partial payment.
</ParamField>

<ParamField body="bankAccountId" type="string" required>
  The ID of the payer bank account to debit. Retrieve available bank account IDs from `GET /v1/bank-accounts`.
</ParamField>

<ParamField body="description" type="string">
  A memo or note to attach to the auto-generated payable. **Applies only when using `contactId` mode.** Ignored when `payableId` is provided.
</ParamField>

<ParamField body="customNumber" type="string">
  A custom reference number for the auto-generated payable, up to 21 characters. **Applies only when using `contactId` mode.** Ignored when `payableId` is provided.
</ParamField>

<ParamField body="categoryId" type="string">
  The ID of a category to assign to the auto-generated line item. **Applies only when using `contactId` mode.** Ignored when `payableId` is provided.
</ParamField>

<ParamField body="clearing" type="string">
  Requested ACH clearing speed. Accepted values: `STANDARD`, `NEXT_AVAILABLE`.

  <Note>
    The `NEXT_AVAILABLE` clearing speed requires that accelerated clearing be enabled on your account. Contact your Cleo Pay account manager to enable this feature.
  </Note>
</ParamField>

<ParamField body="scheduledAt" type="string (date)">
  A future date on which to execute the payment, formatted as `YYYY-MM-DD`. The payment will be initiated at **9:00 AM New York time** on that date.

  Constraints:

  * Must be at least **tomorrow's date** (no same-day scheduling).
  * Not supported for payments that are in `held` status.
</ParamField>

<Note>
  The `description`, `customNumber`, and `categoryId` fields are only meaningful when initiating a payment with `contactId`. They configure the payable that Cleo Pay automatically creates on your behalf. These fields have no effect when `payableId` is supplied.
</Note>

## Response

Returns a `CreatePaymentResponse` object with HTTP status `201 Created`.

<ResponseField name="payableId" type="string">
  The ID of the payable associated with this payment. When using `contactId` mode, this is the ID of the automatically generated payable.
</ResponseField>

<ResponseField name="payments" type="Payment[]">
  Array of one or more `Payment` objects created for this request. The `amountCents` values across all objects sum to the total requested amount.

  <Note>
    Large payment amounts may be automatically split into multiple `Payment` objects by Cleo Pay. Always treat the `payments` array as potentially containing more than one entry.
  </Note>

  <Expandable title="Payment fields">
    <ResponseField name="id" type="string">
      Unique identifier for the payment.
    </ResponseField>

    <ResponseField name="status" type="string">
      Current status of the payment. One of:

      * `pending` — created but not yet submitted
      * `scheduled` — set to execute on a future date
      * `processing` — submitted to the ACH network
      * `held` — flagged for review before processing
      * `completed` — successfully settled
      * `failed` — processing failed; see `failureReason`
      * `cancelled` — cancelled before processing
      * `refunded` — payment was reversed after completion
    </ResponseField>

    <ResponseField name="amountCents" type="number">
      Amount of this specific payment in US cents. May be less than the total requested amount if the payment was split.
    </ResponseField>

    <ResponseField name="contactId" type="string | null">
      ID of the contact associated with this payment.
    </ResponseField>

    <ResponseField name="payableId" type="string | null">
      ID of the payable associated with this payment.
    </ResponseField>

    <ResponseField name="bankAccountId" type="string | null">
      ID of the bank account that was debited.
    </ResponseField>

    <ResponseField name="scheduledAt" type="datetime">
      The scheduled execution datetime for this payment.
    </ResponseField>

    <ResponseField name="processedAt" type="datetime | null">
      ISO 8601 timestamp of when the payment was processed. `null` until processing is complete.
    </ResponseField>

    <ResponseField name="failureReason" type="string | null">
      Human-readable description of why the payment failed. `null` for non-failed payments.
    </ResponseField>

    <ResponseField name="createdAt" type="datetime">
      ISO 8601 timestamp of when the payment was created.
    </ResponseField>

    <ResponseField name="updatedAt" type="datetime">
      ISO 8601 timestamp of the most recent status update.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example Requests

<CodeGroup>
  ```bash payableId mode theme={null}
  curl --request POST \
    --url "https://api.cleo-pay.com/v1/payments" \
    --header "Authorization: Bearer <token>" \
    --header "Content-Type: application/json" \
    --data '{
      "payableId": "pvb_03mn4op5qr6st7uv8wx9yz0a",
      "bankAccountId": "bac_07gh8ij9kl0mn1op2qr3st4u",
      "amountCents": 250000
    }'
  ```

  ```bash contactId mode theme={null}
  curl --request POST \
    --url "https://api.cleo-pay.com/v1/payments" \
    --header "Authorization: Bearer <token>" \
    --header "Content-Type: application/json" \
    --data '{
      "contactId": "cnt_01hq1z2k3m4n5p6q7r8s9t0u",
      "amountCents": 500000,
      "bankAccountId": "bac_07gh8ij9kl0mn1op2qr3st4u",
      "description": "Q1 consulting services",
      "customNumber": "INV-2024-0042",
      "scheduledAt": "2024-04-15"
    }'
  ```
</CodeGroup>

## Example Response

```json 201 theme={null}
{
  "payableId": "pvb_03mn4op5qr6st7uv8wx9yz0a",
  "payments": [
    {
      "id": "pay_09ab1cd2ef3gh4ij5kl6mn7o",
      "status": "scheduled",
      "amountCents": 500000,
      "contactId": "cnt_01hq1z2k3m4n5p6q7r8s9t0u",
      "payableId": "pvb_03mn4op5qr6st7uv8wx9yz0a",
      "bankAccountId": "bac_07gh8ij9kl0mn1op2qr3st4u",
      "scheduledAt": "2024-04-15T13:00:00Z",
      "processedAt": null,
      "failureReason": null,
      "createdAt": "2024-04-10T10:00:00Z",
      "updatedAt": "2024-04-10T10:00:00Z"
    }
  ]
}
```

<Note>
  For very large payment amounts, Cleo Pay may split the transaction into multiple `Payment` objects. The `amountCents` values across all entries in the `payments` array will always sum to the total amount you requested.
</Note>

<Tip>
  To check available bank account IDs for `bankAccountId`, call `GET /v1/bank-accounts` before initiating a payment.
</Tip>
