Skip to main content
Bill Pay is Meow’s accounts-payable surface. You record what you owe a vendor as a bill, including its line items, due date, and how it should be paid, and the API saves it as a draft. Someone on your team approves the bill in the Meow dashboard, and only then does it get paid.
Every bill you touch through the API stays a draft pending approval. Creating a bill, editing it, or attaching documents never moves money on its own. Payment happens only after a human approves the bill in the dashboard.

You’ll need

  • An API key with billpay:read to list and retrieve bills, and billpay:write to create, update, delete, and attach documents to them.
  • A contact for each vendor, created with banking (ACH, wire, or check) counterparty details, or with a crypto_address to pay the vendor in stablecoin. A bill is payable to a contact that must already exist; create one first with POST /contacts. (The Contacts guide covers crypto contacts.)
  • If your key can access more than one entity, pass the x-entity-id header to choose which entity the bill belongs to.

1. Create a bill

A bill is payable to a contact_id and is made of one or more line items. Each line item is either an EXPENSE (a flat amount) or an ITEM (a unit amount times a quantity); the bill total is calculated from the lines. Send a unique Idempotency-Key header so a retried request never creates a duplicate.
Response
Save id. It is the {bill_id} for attaching documents, tracking, updating, or canceling the bill below.
Bill Pay accepts the ACH, WIRE, CHECK, and CRYPTO payment types. A CRYPTO bill must be in USD and names one of the vendor’s saved crypto addresses; the bill’s bill_payment_details.crypto_destination reports the address it will pay. International payments are arranged in the Meow dashboard, not through this API.

2. Attach supporting documents

Supporting documents can include receipts, purchase orders, and related files. The flow has three steps. Request upload URLs, upload each file, and attach the files. You can attach up to five documents in one request.
1

Request upload URLs

Describe each file, giving its filename, content_type, and size in bytes, and get a short-lived upload target for each.
Response
2

Upload each file

POST the file to its url as a multipart form, including every entry from fields and putting the file last. Keep it under max_bytes and upload before the URL expires.
3

Confirm the attachment

Confirm each upload with the object_key and filename you received. The response is the updated bill, now carrying the document under additional_documents with a short-lived download URL.
Response

Attach the primary invoice

Use the invoice endpoints when one file is the vendor’s primary invoice. The invoice can be replaced, and accounting integrations use it as the bill attachment.
  1. Call POST /bills/{bill_id}/invoice/presigned-url with the file details.
  2. Upload the file with the returned URL and fields.
  3. Call POST /bills/{bill_id}/invoice with the returned object_key and filename.
Call DELETE /bills/{bill_id}/invoice to remove the invoice from the bill. Call DELETE /bills/{bill_id}/documents/{document_id} to remove a supporting document.

3. Track bills

GET /bills returns a paginated list and filters by status, vendor, amount, and date ranges, plus full-text search.
Retrieve one bill with GET /bills/{bill_id}:
A bill moves through these statuses as it’s approved and paid:

4. Update or cancel a draft

While a bill is still a DRAFT, you can edit it. PATCH uses partial semantics: only the fields you send change, and sending line_items replaces the existing lines (send an empty list to clear them).
Cancel a bill that hasn’t been approved yet by deleting it:
Once a bill is approved (or paid), it can no longer be edited or deleted through the API.

Update line items without replacing the list

The main PATCH /bills/{bill_id} endpoint can replace the complete line_items list. Use the line-item endpoints when you want to change one line and keep the identifiers and accounting mappings of the other lines.
  • POST /bills/{bill_id}/line-items adds one line.
  • PATCH /bills/{bill_id}/line-items/{line_item_id} updates one line.
  • DELETE /bills/{bill_id}/line-items/{line_item_id} removes one line.

Connect a bill to your accounting system

Read the accounting catalogs before you set mappings:
  • GET /billpay/accounting/vendors
  • GET /billpay/accounting/expense-accounts
  • GET /billpay/accounting/classes
Then call PATCH /bills/{bill_id}/accounting-mappings to map the vendor and default expense account. Use PATCH /bills/{bill_id}/line-items/{line_item_id}/expense-account for a different expense account on one line. Call POST /bills/{bill_id}/sync to retry or refresh an eligible bill in the connected accounting system. The response shows the latest accounting status.
Call GET /billpay/settings before you draft bills. It reports the default funding account, approval count, accounting provider, and required mappings.

5. Schedule recurring bills

To generate a bill on a repeating schedule, include an iCalendar rrule (with a DTSTART) when you create it. Each occurrence is generated as its own draft for approval. Recurring bills are never paid automatically.
Building the schedule string by hand is fiddly. A tool like the RRULE generator will assemble the DTSTART/RRULE for you.
Use GET /bill-schedules to list recurring schedules. Use GET /bill-schedules/{schedule_id} to read one schedule and its generated bills. A schedule starts as DRAFT. It becomes PENDING after submission in the dashboard and ACTIVE after approval. Only an active schedule creates bill drafts. Call POST /bill-schedules/{schedule_id}/cancel to stop future drafts. Existing bills remain unchanged, and a canceled schedule cannot become active again.

Estimate delivery dates

Call GET /billpay/expected-payment-date before you create a bill when the delivery date determines the payment rail. The endpoint uses banking days and account cutoff times. It returns an estimate and does not reserve or send funds.

End to end

The bill now sits as a DRAFT with its invoice attached, waiting for an approver in the dashboard.

Bulk loads

There is no batch endpoint. To load a run of bills — a month of contractor payments, for example — call POST /bills once per bill. Two things make a large run safe to retry:
  • Give every bill its own Idempotency-Key, derived from your own record (a payroll row id, an invoice number). Replaying the whole run then re-sends the same key per bill, so nothing is duplicated.
  • Create the vendor contacts first. A bill needs a contact that already carries the banking details for its payment type, so resolve or create contacts before the run rather than inside it.
Drafting is capped at 500 bills per rolling 24 hours per creator — your entity key, or the user a user-scoped key acts as. Creates past the cap return 429 Too Many Requests; retry after the oldest drafts in the window age out, or split the run across keys. Every bill still lands as a DRAFT awaiting approval in the dashboard, so a bulk load never moves money on its own.

See also

Create a contact

Register a vendor with banking counterparty details to pay bills to.

Create a bill

Full request contract for POST /bills.

List bills

Every filter, sort, and pagination option.

Update a bill

Edit a draft with PATCH partial semantics.

Confirm bill documents

Attach uploaded receipts and supporting files.

Bill Pay settings

Read the default funding account and accounting requirements.

List bill schedules

Track recurring schedules and the bills they create.