Skip to content

Accounts Payable

The Accounts Payable API reads the counterparties of the business linked to your API Access Token, and the bills it owes them. These endpoints require the accounts_payable:read scope and are read-only.

Beta

The Accounts Payable API is in Beta. Additive changes are normal, and breaking changes may be made with notice while the resource incorporates customer feedback. See Versioning and compatibility.

Use Accounts Payable to read who you pay and what you owe: the same counterparty and bill records shown in the Rho product. Each counterparty carries the stable id that bills and payments reference as payee, and each bill carries its due date, approval and payment state, line items, and attached invoice file.

List counterparties

GET /api/v1/ap/counterparties returns a paginated list of counterparties. search is a case-insensitive substring match on legal_name and nickname. Filter by one or more status values, sort with sort_by and order, and keep every filter unchanged while paginating.

curl "https://rhoapi.rho.co/api/v1/ap/counterparties?search=acme&status=active&sort_by=legal_name&order=asc&page_size=20" \
  -H "Authorization: Bearer $RHO_API_TOKEN"
ParameterValuesDefaultDescription
searchstring-Case-insensitive substring match on legal_name and nickname.
statusincomplete, invited, active, archivedallRepeatable. Filters by derived display status.
sort_bycreated_at, legal_namecreated_atSort field.
orderasc, descdescSort direction.
page_size1-10020Counterparties per page.
page_tokenstring-Cursor from page.next_page_token. Omit for the first page.

Follow the cursor as described in Pagination until next_page_token is null. Page tokens belong to the API version and the filters that created them, so restart pagination when migrating from v0 to v1 or when any filter changes.

{
  "counterparties": [
    {
      "id": "3f2b1a44-9c1e-4a8b-bb0e-8b7c2d5e1a90",
      "legal_name": "Acme Supplies LLC",
      "nickname": "Acme",
      "email": "ap@acmesupplies.com",
      "phone_number": "+12125550123",
      "registration_country_code": "US",
      "memo": "Preferred office supplier",
      "status": "active",
      "is_business": true,
      "w9_status": "complete",
      "address": {
        "street": "123 Market St",
        "second_line": "Suite 400",
        "city": "New York",
        "subdivision": "NY",
        "postal_code": "10001",
        "country_code": "US"
      },
      "payment_methods": [
        {
          "id": "6d083d95-6e5f-4ec3-b125-6eb41cddc63f",
          "type": "ach",
          "is_default": true,
          "description": "Checking ending in 1234",
          "bank_name": "Example Bank",
          "currency": "USD",
          "country_code": "US"
        },
        {
          "id": null,
          "type": "single_use_card",
          "is_default": false,
          "description": "Single-use virtual card",
          "currency": "USD",
          "country_code": "US"
        }
      ],
      "created_at": "2026-07-01T14:32:07Z",
      "updated_at": "2026-07-20T09:15:42Z"
    }
  ],
  "page": {
    "next_page_token": null
  }
}

Fields that are not on file are omitted from the response rather than returned as empty strings - nickname, email, phone_number, registration_country_code, memo, w9_status, and address are all optional.

Get a counterparty

GET /api/v1/ap/counterparties/{counterparty_id} returns one counterparty by its stable id, in the same shape as a list entry. A counterparty that does not belong to your business returns 404 Not Found.

curl "https://rhoapi.rho.co/api/v1/ap/counterparties/3f2b1a44-9c1e-4a8b-bb0e-8b7c2d5e1a90" \
  -H "Authorization: Bearer $RHO_API_TOKEN"

Status

status is derived for display and collapses several underlying states:

StatusMeaning
incompleteA draft missing something needed to pay it - business type, legal name, or a default payment method - or one that failed validation.
invitedA draft with an unexpired portal invite outstanding, waiting on the counterparty to complete their own details.
activeReady to be paid.
archivedArchived in the Rho product and no longer offered as a payee.

Archived counterparties are returned like any other, so filter on status=incomplete&status=invited&status=active to exclude them, or status=archived to read only them. They stay readable because bills and payments keep referencing a counterparty after it is archived.

W-9 status

w9_status is absent when there is no W-9 on file. When present:

StatusMeaning
completeA W-9 was collected through Rho.
complete_externallyA W-9 exists but was collected outside Rho.
sent_pendingA W-9 request was sent and is awaiting the counterparty.

Payment methods

payment_methods lists the non-archived payment methods on file, in the order Rho displays them: domestic (ACH or wire), international, check, vendor cards, then a single-use card. At most one is is_default.

TypeNotes
achDomestic ACH. currency is USD; no address.
wireDomestic wire. Carries the beneficiary address when on file.
checkaddress is the check shipping address.
internationalbank_name, currency, and country_code come from the beneficiary bank.
vendor_cardA card issued to this counterparty.
single_use_cardAvailable when the counterparty has an email on file. id is null.

id is null on a single_use_card entry. A single-use card is minted per payment rather than kept on file, so there is no stored record for an id to name. Every other type carries one. The key is always present, so a null id means this type has none rather than that the value went missing. Key off type to tell the entries apart, and expect a null wherever you read payment_methods[].id.

Only non-sensitive payment method metadata is exposed. Bank account and routing numbers are not returned under accounts_payable:read.

Counterparty notes and limitations

  • is_business is false when the counterparty's type is not yet known, which happens on incomplete counterparties. It does not confirm the counterparty is an individual.
  • Archived payment methods are omitted, and only the first check detail is returned when a counterparty has more than one.
  • Counterparties are returned as standalone payees. Related bills are not embedded.
  • These endpoints are read-only. Creating, editing, inviting, and archiving counterparties are not available.

List bills

GET /api/v1/ap/bills returns a paginated list of bills. Search matches payee name and email, creator name, invoice number, and amount.

curl "https://rhoapi.rho.co/api/v1/ap/bills?status=scheduled&sort_by=due_date&order=asc&page_size=20" \
  -H "Authorization: Bearer $RHO_API_TOKEN"
ParameterTypeDescription
searchstringFree-text match across payee name and email, creator name, invoice number, and amount.
statusBillStatus[]Repeat the parameter to filter on several statuses.
due_date_afterdateEarliest due date to include, inclusive.
due_date_beforedateLatest due date to include, inclusive.
created_afterdate-timeEarliest creation time to include, inclusive.
created_beforedate-timeLatest creation time to include, exclusive.
sort_byenumcreated_at (default), due_date, or amount.
orderenumasc or desc, defaults to desc.
page_sizeinteger1 to 100, defaults to 20.
page_tokenstringCursor from page.next_page_token.

Follow the cursor as described in Pagination until next_page_token is null, and keep filters and sorting unchanged while paginating. Page tokens belong to the API version and the filters that created them, so restart pagination when migrating from v0 to v1.

{
  "bills": [
    {
      "id": "3f2b1a44-9c1e-4a8b-bb0e-8b7c2d5e1a90",
      "status": "scheduled",
      "amount": {"amount": 120050, "currency": "USD"},
      "counterparty": {"id": "7a1c0b22-8d33-4dd9-9d5d-b3171c4c3d71"},
      "invoice_number": "BILL-2026-0042",
      "invoice_date": "2026-07-24",
      "due_date": "2026-08-01",
      "lines": [
        {
          "id": "f6b24a27-4a89-4a89-ae0b-4f4212dd5a15",
          "index": 1,
          "amount": {"amount": 100000, "currency": "USD"},
          "description": "Consulting Services - July",
          "created_by_user_id": "a8d32021-5c7d-45f8-8be7-65e9d48db4ec",
          "created_at": "2026-07-01T14:32:07Z",
          "updated_at": "2026-07-20T09:15:42Z"
        }
      ],
      "file_id": "d8593b96-f0f4-4d36-8a5c-7d7d7b9f910a",
      "transaction": {"id": "6ef5df3b-50d5-4d7b-9877-dcf8127f1a8d"},
      "payment_date": "2026-08-01",
      "memo": "Net 30 terms apply.",
      "created_at": "2026-07-01T14:32:07Z",
      "updated_at": "2026-07-20T09:15:42Z"
    }
  ],
  "page": {
    "next_page_token": null
  }
}

Amounts use the currency's smallest unit (cents for USD), so 120050 is $1,200.50. When a bill is itemized, its line amounts sum to amount; lines is empty otherwise. A bill that has no amount set yet - a draft still being filled in, for instance - leaves amount out of the response entirely, so read it as optional rather than defaulting to zero.

counterparty and transaction carry only an identifier. Read the full counterparty record from GET /api/v1/ap/counterparties/{counterparty_id}, and the settled payment from the transactions endpoints.

Bill status

status folds bill state, approval stage, and payment state into one value.

StatusMeaning
draftNot yet submitted for payment.
missing_payment_detailsSubmitted, but blocked until the payment details it needs are on file.
awaiting_approvalPending one or more approvals.
ready_for_paymentApproved and payable, not yet scheduled.
scheduledPayment scheduled for a future date.
pending_paymentPayment in flight, not yet settled.
paidPayment settled.
failed_paymentPayment failed.
archivedThe bill or its payment was archived.
otherA state that does not map to any value above.

The table is roughly in lifecycle order, but a bill does not necessarily pass through every state and the order is not guaranteed - don't infer progress from it. Treat other as a catch-all rather than a stable state: new states surface there before they get their own value.

scheduled does not guarantee a payment_date. A bill can be scheduled upstream before a date is attached, so read the two independently.

Get a bill

GET /api/v1/ap/bills/{bill_id} returns one bill by ID. A bill belonging to another business responds 404, the same as one that does not exist.

curl "https://rhoapi.rho.co/api/v1/ap/bills/3f2b1a44-9c1e-4a8b-bb0e-8b7c2d5e1a90" \
  -H "Authorization: Bearer $RHO_API_TOKEN"

Download a bill file

GET /api/v1/ap/bills/{bill_id}/files/{file_id} returns file_id, file_name, and a fresh short-lived signed download_url. file_id must match bill.file_id from list/get when that field is set. Fetch again whenever you need a new signed URL; do not persist the URL.

curl "https://rhoapi.rho.co/api/v1/ap/bills/3f2b1a44-9c1e-4a8b-bb0e-8b7c2d5e1a90/files/d8593b96-f0f4-4d36-8a5c-7d7d7b9f910a" \
  -H "Authorization: Bearer $RHO_API_TOKEN"
{
  "file_id": "d8593b96-f0f4-4d36-8a5c-7d7d7b9f910a",
  "file_name": "BILL-2026-0042.pdf",
  "download_url": "https://files.example/bill.pdf?signature=..."
}

Reference

Full endpoint catalogue - paths, parameters, response shapes, and required scopes - lives in the API Reference.