ARPilot API (1.6.0)

Download OpenAPI specification:

RESTful API for managing accounts receivable data in ARPilot. Authenticate with API keys (Bearer token). Available on Pro and Enterprise tiers.

Invoices

List invoices

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25
status
string
customer_id
string <uuid>

Responses

Create an invoice

Create an invoice manually or from line items. Either amount (legacy single-line) or line_items[] (with optional tax_amount / discount_amount) must produce a positive total. If both are provided, line-items math must match amount within $0.01.

invoice_number is optional — if omitted, the server generates one in the format {prefix}-{YYYY}-{NNNN} (prefix defaults to INV, configurable per tenant; sequence resets each calendar year).

After creation, the invoice status is automatically recalculated from its financial fields (amount, amount_due, external_payment_amount). For example, if amount_due is 0, status will be auto-corrected to 'paid' regardless of the status provided. Terminal statuses ('cancelled', 'draft') are respected and not auto-corrected.

source_type is set to api on every invoice created through this endpoint so the platform can distinguish API-originated invoices from QuickBooks imports for future two-way sync.

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
invoice_number
string

Optional. Auto-generated as {prefix}-{YYYY}-{NNNN} if omitted.

customer_id
required
string <uuid>

UUID of an existing customer. Customer must belong to your account.

customer_name
string

Overrides the customer's company_name on this invoice. Auto-populated from customer if omitted.

customer_address
string
amount
number

Required if line_items is omitted. If both are present, must equal sum(line_items) + tax_amount - discount_amount within $0.01.

amount_due
number

Defaults to amount if omitted. If less than amount, the difference is stored as external_payment_amount.

Array of objects

Optional. When provided, the server derives amount from sum(line_items) + tax_amount - discount_amount and inserts the items into invoice_line_items. A failed line-items insert rolls back the invoice header.

tax_amount
number >= 0
Default: 0

Single tax line on the whole invoice. US-only, no per-line tax.

tax_rate
number [ 0 .. 1 ]

Display-only effective tax rate (e.g. 0.0875 for 8.75%). The source of truth is tax_amount.

discount_amount
number >= 0
Default: 0
currency
string
Default: "USD"
Value: "USD"
issue_date
string <date>

Defaults to today if omitted

due_date
required
string <date>
status
string
Default: "pending"
Enum: "draft" "pending" "overdue" "partial" "paid" "in_payment_plan" "in_dispute" "cancelled"
notes
string
generate_pdf
boolean
Default: false

Optional. When true, ARPilot renders a branded invoice PDF on create using the tenant's user_branding row, attaches it to the invoice (pdf_source: 'arpilot_generated'), and returns the signed URL in data.pdf.pdf_signed_url. Defaults to false — invoices imported from accounting platforms or used for collections-only stay PDF-less unless explicitly asked.

Responses

Request samples

Content type
application/json
{
  • "invoice_number": "string",
  • "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
  • "customer_name": "string",
  • "customer_address": "string",
  • "amount": 0,
  • "amount_due": 0,
  • "line_items": [
    ],
  • "tax_amount": 0,
  • "tax_rate": 1,
  • "discount_amount": 0,
  • "currency": "USD",
  • "issue_date": "2019-08-24",
  • "due_date": "2019-08-24",
  • "status": "draft",
  • "notes": "string",
  • "generate_pdf": false
}

Get invoice by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update an invoice

When financial fields (amount, amount_due, external_payment_amount, status) are modified, the invoice balance and status are automatically recalculated. Cross-field validation ensures amount_due cannot exceed amount and external_payment_amount cannot exceed amount. Terminal statuses ('cancelled', 'draft') bypass auto-recalculation and are applied directly.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
customer_name
string
customer_address
string
amount
number

Must be positive

amount_due
number

Must be non-negative and cannot exceed amount

external_payment_amount
number

Must be non-negative and cannot exceed amount

issue_date
string <date>
due_date
string <date>
status
string
Enum: "draft" "pending" "overdue" "partial" "paid" "in_payment_plan" "in_dispute" "cancelled"
notes
string

Responses

Request samples

Content type
application/json
{
  • "customer_name": "string",
  • "customer_address": "string",
  • "amount": 0,
  • "amount_due": 0,
  • "external_payment_amount": 0,
  • "issue_date": "2019-08-24",
  • "due_date": "2019-08-24",
  • "status": "draft",
  • "notes": "string"
}

PDF actions or send the invoice

Four actions selectable via ?action=:

  • upload_pdf — attach a caller-supplied base64-encoded PDF (sets pdf_source: 'user_upload').
  • delete_pdf — remove the current PDF and clear pdf_source.
  • generate_pdf — render a branded PDF on the server using the tenant's user_branding (sets pdf_source: 'arpilot_generated'). Returns 409 if the invoice already has a user_upload or quickbooks PDF — delete it first. Regenerating over an existing arpilot_generated PDF is idempotent.
  • send — send the invoice to its customer using a chosen email template, immediately or scheduled. Requires template_id (an email template with template_stage='initial_send' — discover via GET /v1/templates). Optional scheduled_date (ISO-8601; omit for send-now). Optional cc_self. Flips invoice status draft → pending idempotently. No source_type restriction — works on QuickBooks-imported invoices too.

Uploading replaces any existing PDF.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
query Parameters
action
required
string
Enum: "upload_pdf" "delete_pdf" "generate_pdf" "send"

upload_pdf — attach a PDF; delete_pdf — remove the current attachment; generate_pdf — render a branded PDF server-side; send — dispatch the invoice to the customer using a template

Request Body schema: application/json
optional
pdf_base64
string

Base64-encoded PDF file content. Required when action=upload_pdf. Ignored for delete_pdf, generate_pdf, and send.

template_id
string <uuid>

Required when action=send. UUID of an email template with template_stage='initial_send'. Discover candidates via GET /v1/templates.

scheduled_date
string <date-time>

Used by action=send only. ISO-8601 timestamp. Omit (or pass null) to send immediately; past timestamps also send immediately. Future timestamps queue the send until that moment.

cc_self
boolean

Used by action=send only. Default false. When true, CCs the tenant account email on the outgoing message.

Responses

Request samples

Content type
application/json
{
  • "pdf_base64": "string",
  • "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  • "scheduled_date": "2019-08-24T14:15:22Z",
  • "cc_self": true
}

Templates

List invoice-send templates

Returns a paginated list of email templates eligible to use with POST /v1/invoices/{id}?action=send. Filters: type='email' AND template_stage='initial_send'. Dunning / collections templates are excluded — they're not valid first-touch sends. Includes templates owned by the key holder (user_id matches) plus system templates (user_id IS NULL). Read-only by design — template authoring lives in the ARPilot UI. Reuses the invoices API key scope; no separate scope to rotate.

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25

Responses

Customers

List customers

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25
search
string
tag_id
string <uuid>

Filter by tag UUID

Responses

Create a customer

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
company_name
required
string
customer_id
string

Your internal customer ID. Auto-generated if omitted.

address
string
required
Array of objects non-empty

At least one contact required. Each contact must have contact_name and email.

tags
Array of strings

Tag names (auto-created if new)

Responses

Request samples

Content type
application/json
{
  • "company_name": "string",
  • "customer_id": "string",
  • "address": "string",
  • "contacts": [
    ],
  • "tags": [
    ]
}

Get customer by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update a customer

Update customer fields, tags, and/or contacts. Contacts use upsert semantics: include 'id' to update an existing contact, omit 'id' to create a new one. Contacts not mentioned in the array are left untouched. When contact email, name, or phone changes, pending scheduled communications are automatically refreshed.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
company_name
string
address
string
timezone
string

IANA timezone (e.g. America/New_York)

tags
Array of strings

Replace all tags (UUIDs or names)

Array of objects

Upsert contacts: include 'id' to update existing, omit to create new. Non-mentioned contacts are untouched.

delete_contact_ids
Array of strings <uuid> [ items <uuid > ]

UUIDs of contacts to delete. Cannot delete the last contact.

Responses

Request samples

Content type
application/json
{
  • "company_name": "string",
  • "address": "string",
  • "timezone": "string",
  • "tags": [
    ],
  • "contacts": [
    ],
  • "delete_contact_ids": [
    ]
}

Delete a customer

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Payments

List payments

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25
invoice_id
string <uuid>
reviewed
string
Enum: "true" "false"

Responses

Record a payment

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
amount
required
number
payment_date
required
string <date>
payment_method
string

e.g. ach, check, wire, other

payer_name
string
payer_reference
string
external_payment_id
string

Your system's payment ID (auto-generated if omitted)

notes
string

Responses

Request samples

Content type
application/json
{
  • "amount": 0,
  • "payment_date": "2019-08-24",
  • "payment_method": "string",
  • "payer_name": "string",
  • "payer_reference": "string",
  • "external_payment_id": "string",
  • "notes": "string"
}

Get payment by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update / match payment

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
invoice_id
string <uuid>

Set to a valid UUID to match; null to unmatch

payer_name
string
payer_reference
string
reviewed
boolean
notes
string

Responses

Request samples

Content type
application/json
{
  • "invoice_id": "f4c4edb8-11e0-4b33-bcc1-482dc59ebb32",
  • "payer_name": "string",
  • "payer_reference": "string",
  • "reviewed": true,
  • "notes": "string"
}

Tags

List tags

Authorizations:
ApiKeyAuth

Responses

Create a tag

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
name
required
string
color
string

Hex color (auto-assigned if omitted)

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "color": "string"
}

Get tag by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update a tag

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
name
string
color
string

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "color": "string"
}

Delete a tag

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Assign tag to customers

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
customer_ids
required
Array of strings <uuid> [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "customer_ids": [
    ]
}

Remove tag from customers

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
customer_ids
required
Array of strings <uuid> [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "customer_ids": [
    ]
}

Bulk add/remove tags across customers

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
customer_ids
required
Array of strings <uuid> [ items <uuid > ]
add_tag_ids
Array of strings <uuid> [ items <uuid > ]
remove_tag_ids
Array of strings <uuid> [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "customer_ids": [
    ],
  • "add_tag_ids": [
    ],
  • "remove_tag_ids": [
    ]
}

Contacts

List contacts for a customer

Returns paginated contacts for a given customer, ordered by escalation_level.

Authorizations:
ApiKeyAuth
query Parameters
customer_id
required
string <uuid>

Customer UUID (required)

page
integer
Default: 1
per_page
integer <= 100
Default: 25

Responses

Create a contact

Create a new contact for a customer. Requires customer_id, contact_name, and email. When created, if email/phone triggers downstream changes, scheduled communications are updated automatically.

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
customer_id
required
string <uuid>
contact_name
required
string
email
required
string <email>
phone
string or null
phone_type
string or null
Enum: "mobile" "home" "work" "office" "fax" "other"
phone_secondary
string or null
phone_type_secondary
string or null
Enum: "mobile" "home" "work" "office" "fax" "other"
is_primary
boolean
Default: false
escalation_level
integer
Default: 0
title
string or null
notes
string or null

Responses

Request samples

Content type
application/json
{
  • "customer_id": "160c0c4b-9966-4dc1-a916-8407eb10d74e",
  • "contact_name": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "phone_type": "mobile",
  • "phone_secondary": "string",
  • "phone_type_secondary": "mobile",
  • "is_primary": false,
  • "escalation_level": 0,
  • "title": "string",
  • "notes": "string"
}

Get contact by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update a contact

Update contact fields. Only include fields you want to change. Changes to email, name, or phone automatically refresh pending scheduled communications.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
contact_name
string
email
string <email>
phone
string or null
phone_type
string or null
Enum: "mobile" "home" "work" "office" "fax" "other"
phone_secondary
string or null
phone_type_secondary
string or null
Enum: "mobile" "home" "work" "office" "fax" "other"
is_primary
boolean
escalation_level
integer
title
string or null
notes
string or null

Responses

Request samples

Content type
application/json
{
  • "contact_name": "string",
  • "email": "user@example.com",
  • "phone": "string",
  • "phone_type": "mobile",
  • "phone_secondary": "string",
  • "phone_type_secondary": "mobile",
  • "is_primary": true,
  • "escalation_level": 0,
  • "title": "string",
  • "notes": "string"
}

Delete a contact

Delete a contact. Cannot delete the last contact for a customer. If the deleted contact was primary, the next contact by escalation_level is auto-promoted.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Webhooks

List webhook endpoints

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25

Responses

Register a webhook endpoint

Register a new HTTPS endpoint to receive events. The signing secret is returned only in this response and cannot be retrieved again.

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
url
required
string

Destination URL (must be https://)

events
Array of strings
Items Enum: "*" "reconciliation.record_created" "reconciliation.record_updated" "invoice.created" "invoice.updated" "payment.created" "payment.matched" "customer.created" "customer.updated" "dispute.created" "dispute.resolved" "payment_plan.enrolled" "payment_plan.completed" "webhook.test"

Event types to subscribe to. Use ["*"] for all events.

description
string or null

Responses

Request samples

Content type
application/json
{
  • "url": "string",
  • "events": [
    ],
  • "description": "string"
}

Get webhook endpoint

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Update webhook endpoint

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
Request Body schema: application/json
required
url
string
events
Array of strings
Items Enum: "*" "reconciliation.record_created" "reconciliation.record_updated" "invoice.created" "invoice.updated" "payment.created" "payment.matched" "customer.created" "customer.updated" "dispute.created" "dispute.resolved" "payment_plan.enrolled" "payment_plan.completed" "webhook.test"
description
string or null
is_active
boolean

Responses

Request samples

Content type
application/json
{
  • "url": "string",
  • "events": [
    ],
  • "description": "string",
  • "is_active": true
}

Delete webhook endpoint

Permanently deletes the endpoint and all delivery history.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

Send a test event

Queues a webhook.test event to this endpoint so you can verify your server receives and validates signatures correctly.

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses

List delivery attempts

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>
query Parameters
status
string
Enum: "pending" "delivered" "failed" "abandoned"
page
integer
Default: 1
per_page
integer
Default: 25

Responses

Reconciliation

List approved accounting changes

Authorizations:
ApiKeyAuth
query Parameters
page
integer
Default: 1
per_page
integer <= 100
Default: 25
change_type
string
Enum: "payment" "adjustment" "discount" "credit" "financing_fee" "processing_fee"
invoice_id
string <uuid>
customer_id
string <uuid>

Responses

Mark accounting changes as synced or failed

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
action
required
string
Enum: "mark_synced" "mark_failed"

Action to perform on the changes

change_ids
required
Array of strings <uuid> [ items <uuid > ]

UUIDs of accounting changes to update

error_message
string

Error description (only for mark_failed)

Responses

Request samples

Content type
application/json
{
  • "action": "mark_synced",
  • "change_ids": [
    ],
  • "error_message": "string"
}

Get accounting change by ID

Authorizations:
ApiKeyAuth
path Parameters
id
required
string <uuid>

Responses