Agree API Documentation
- Introduction
- What You Can Do
- Quick Start
- How Resources Connect
- Base URL
- Authentication
- Request Format
- Response Format
- Errors
- Pagination
- Need Help?
- Agreements
- Overview
- Creating an Agreement
- Daisy-Chaining: Attaching an Invoice to an Agreement
- Recipient Roles
- Field Values (Prefilling)
- Custom Variables (Template Variables)
- Listing Agreements
- Sending an Agreement
- Create and Send in One Step
- Updating an Agreement
- Agreement Statuses
- Fields Reference
- getDownload agreement PDF
- postSend agreement
- postCreate and send agreement
- getList agreement templates
- getList agreements
- postCreate agreement from template
- getGet template
- delDelete agreement
- getGet agreement
- patchUpdate agreement
- putUpdate agreement
- Invoices
- Overview
- Common Use Cases
- Creating an Invoice
- Invoice Lifecycle
- Recurring Invoices
- Listing and Filtering Invoices
- Sending an Invoice
- Updating an Invoice
- Downloading invoice and receipt PDFs
- Canceling an Invoice
- Fields Reference
- getDownload receipt PDF
- postMark invoice as sent
- postSend invoice
- getList invoices
- postCreate invoice
- getDownload invoice PDF
- delDelete invoice
- getGet invoice
- patchUpdate invoice
- putUpdate invoice
- postCreate and send invoice
- postMark invoice as paid
- Contacts
- Overview
- Creating a Contact
- Using Contacts with Invoices
- Listing and Filtering Contacts
- Updating a Contact
- Deleting a Contact
- Fields Reference
- getList contacts
- postCreate contact
- delDelete contact
- getGet contact
- patchUpdate contact
- putUpdate contact
- Webhooks
- Overview
- Quick Setup
- Available Events
- Webhook Payload
- Verifying Webhooks
- Managing Endpoints
- Retry Policy
- Best Practices
- Fields Reference
- getList webhook endpoints
- postCreate webhook endpoint
- delDelete webhook endpoint
- getGet webhook endpoint
- patchUpdate webhook endpoint
- putUpdate webhook endpoint
- postSend test webhook
- Reports
- Overview
- Revenue
- Cashflow
- Recovery
- getRevenue statistics
- getAging trend
- getRevenue chart data
- getStage duration statistics
- getLeakage statistics
- getLeakage waterfall
- getCashflow chart data
- getStalled invoices
- getCash forecast
- getCustomers by MRR
- getOutstanding invoices
- getCashflow statistics
- getCustomers by revenue
- getAging chart data
- getInvoices by aging bucket
API docs by Redocly](https://redocly.com/redoc/)
Agree API (1.0.0)
Download OpenAPI specification: Download
section/Introduction Introduction
Welcome to the Agree API! Agree is a payments and agreements platform that helps businesses send invoices, collect payments, and manage customer relationships. This API lets you integrate Agree's capabilities directly into your application.
section/Introduction/What-You-Can-Do What You Can Do
With the Agree API, you can:
- Create and send invoices to customers with flexible payment options (ACH, credit card, wire transfer)
- Manage contacts in your organization's address book
- Set up recurring invoices with customizable schedules
- Receive real-time notifications via webhooks when payments are made or invoices change status
- Track payment status and history programmatically
section/Introduction/Quick-Start Quick Start
Here's how to send your first invoice in three API calls:
1. Get Your API Key
Generate an API key in your Agree dashboard under Settings > API Keys. Keep this key secure - it provides full access to your organization's data.
2. Create a Contact
First, add the customer you want to invoice:
curl -X POST https://api.agree.com/api/v1/contacts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact": {
"name": "Jane Smith",
"email": "jane@example.com",
"company": "Acme Corp"
}
}'
3. Create and Send an Invoice
Now create and send an invoice for that contact. You can use the convenience endpoint to do both in one request:
curl -X POST https://api.agree.com/api/v1/invoices/create_and_send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "jane@example.com"
},
"amount": {"amount": 10000, "currency": "USD"},
"payment_methods": ["card", "ach"],
"due_at": "2025-02-01T00:00:00Z",
"memo": "Consulting services - January 2025"
}
}'
The invoice will be created and immediately sent to the customer via email. They'll receive a payment link where they can pay using their preferred method.
Alternative: You can also create the invoice first with POST /api/v1/invoices, then send it later with POST /api/v1/invoices/:id/send if you need to review or modify it before sending.
4. Get Notified When They Pay
Set up a webhook to know when the invoice is paid:
curl -X POST https://api.agree.com/api/v1/webhook_endpoints \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_endpoint": {
"url": "https://your-app.com/webhooks/agree",
"events": ["invoice.paid", "invoice.failed"]
}
}'
Save the secret from the response - you'll need it to verify webhook signatures.
section/Introduction/How-Resources-Connect How Resources Connect
Understanding how Agree's resources relate to each other will help you build effective integrations:
Contacts ──────► Invoices ──────► Webhooks
│ │ │
│ │ │
▼ ▼ ▼
People you Payment Real-time
do business requests notifications
with you send when things
to contacts happen
Contacts are people or companies in your address book. You can create contacts explicitly, or they're created automatically when you send an invoice to a new email address.
Invoices are payment requests sent to contacts. Each invoice has an amount, due date, and accepted payment methods. Invoices progress through a lifecycle from created → sent → paid (or failed/canceled).
Webhooks notify your application when invoice events occur. This lets you update your systems in real-time without polling.
section/Introduction/Base-URL Base URL
All API requests should be made to:
https://api.agree.com/api/v1
section/Introduction/Authentication Authentication
All endpoints require Bearer token authentication. Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Keep your API key secure. If compromised, regenerate it immediately in your dashboard.
section/Introduction/Request-Format Request Format
Send request bodies as JSON with the Content-Type: application/json header.
section/Introduction/Response-Format Response Format
All successful responses return JSON with a data wrapper:
{
"data": { ... }
}
List endpoints include pagination information:
{
"data": [ ... ],
"pagination": {
"page": 1,
"page_size": 10,
"total_pages": 5,
"total_entries": 42
}
}
section/Introduction/Errors Errors
Errors return appropriate HTTP status codes with details:
| Status | Description |
|---|---|
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 403 | Forbidden - No access to this resource |
| 404 | Not Found - Resource doesn't exist |
| 422 | Unprocessable Entity - Validation errors |
Error responses include field-specific messages:
{
"errors": {
"email": ["has already been taken"],
"amount": ["must be greater than 0"]
}
}
section/Introduction/Pagination Pagination
List endpoints support pagination with these query parameters:
| Parameter | Default | Description |
|---|---|---|
page |
1 | Page number to retrieve |
page_size |
10 | Number of items per page (max: 100) |
section/Introduction/Need-Help Need Help?
- Check the endpoint documentation below for detailed parameter information
- Test webhooks using the
webhook.testevent - Contact support@agree.com for API assistance
tag/Agreements Agreements
Create, send, and manage agreements with recipients and field assignments.
tag/Agreements/Overview Overview
Agreements are documents that require signatures from one or more recipients. Each agreement is created from a template and can have specific fields (like signature fields, date fields, text fields) assigned to specific recipients.
Key concepts:
- Agreements are created from templates
- Each agreement must have exactly one recipient with the
ownerrole (the account holder) - Fields can be assigned to specific recipients via
assigned_fields - Agreements can include invoices for payment collection
- Recipients can be specified by
contact_idor by providing contact details inline
tag/Agreements/Creating-an-Agreement Creating an Agreement
Basic Agreement Creation
Here's a basic example of creating an agreement from a template:
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement",
"recipients": [\
{\
"contact_id": "770e8400-e29b-41d4-a716-446655440000",\
"role": "owner"\
},\
{\
"contact_id": "880e8400-e29b-41d4-a716-446655440000",\
"role": "signer"\
}\
]
}'
The Owner Role Requirement
Important: When creating an agreement, exactly one recipient must be assigned the owner role. This recipient must be the account holder (the person whose API key is being used). The owner is the person initiating the agreement creation.
Common mistake: If you assign yourself as a signer instead of owner, the request will fail with a validation error.
Correct approach:
{
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner"\
},\
{\
"contact_id": "CLIENT_CONTACT_ID",\
"role": "signer"\
}\
]
}
Incorrect approach (will fail):
{
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "signer" // ❌ Wrong - must be "owner"\
}\
]
}
Finding Your Contact ID
The account holder (you) is also a contact in your organization. To find your own Contact ID:
curl https://api.agree.com/api/v1/contacts \
-H "Authorization: Bearer YOUR_API_KEY"
This returns a list of all contacts in your organization, including yourself. Look for the contact with your email address - that's your Contact ID. You can also filter by email:
curl "https://api.agree.com/api/v1/contacts?email=your-email@example.com" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"data": [\
{\
"id": "770e8400-e29b-41d4-a716-446655440000",\
"name": "Your Name",\
"email": "your-email@example.com",\
"company": "Your Company",\
...\
}\
],
"pagination": {
"page": 1,
"page_size": 10,
"total_pages": 1,
"total_entries": 1
}
}
Use the id field from the contact that matches your email address as your contact_id when creating agreements.
Assigning Fields to Recipients
When creating an agreement, you can assign specific fields to specific recipients. Fields are identified by their field IDs (as defined in the template).
Example: Assigning Fields
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement",
"recipients": [\
{\
"contact_id": "770e8400-e29b-41d4-a716-446655440000",\
"role": "owner",\
"assigned_fields": ["company_address", "date"]\
},\
{\
"contact_id": "880e8400-e29b-41d4-a716-446655440000",\
"role": "signer",\
"assigned_fields": ["signature_field", "date_field"]\
}\
]
}'
In this example:
- The owner is assigned
company_addressanddatefields - The signer is assigned
signature_fieldanddate_fieldfields
Field Assignment Rules:
- Field IDs must match exactly as defined in the template
- Fields not assigned to any recipient will be assigned to the owner by default
- You can assign multiple fields to the same recipient
- The same field cannot be assigned to multiple recipients
Complete Example with All Options:
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement with Invoice",
"delivery_mode": "managed",
"field_values": {
"field_1": "John Doe",
"field_2": "2024-01-01"
},
"recipients": [\
{\
"contact_id": "770e8400-e29b-41d4-a716-446655440000",\
"role": "owner",\
"assigned_fields": ["company_address", "date"]\
},\
{\
"contact": {\
"email": "client@example.com",\
"name": "Jane Smith",\
"company": "Client Corp"\
},\
"role": "signer",\
"assigned_fields": ["signature_field", "date_field"]\
}\
],
"signing_order_enabled": false,
"payments_enabled": true,
"reminder_schedule": "weekly",
"invoice": {
"billing_contact": {
"email": "client@example.com",
"name": "Jane Smith"
},
"amount": 15000,
"currency": "USD",
"memo": "Payment for services",
"payment_methods": ["card", "ach"],
"payment_terms_type": "net",
"payment_terms_days": 30
}
}'
tag/Agreements/Daisy-Chaining:-Attaching-an-Invoice-to-an-Agreement Daisy-Chaining: Attaching an Invoice to an Agreement
There are two ways to attach an invoice to an agreement:
Option 1: Create Agreement with Invoice (Single Request)
The simplest approach is to include the invoice in the agreement creation request:
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement with Invoice",
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner"\
},\
{\
"contact_id": "CLIENT_CONTACT_ID",\
"role": "signer"\
}\
],
"invoice": {
"billing_contact": {
"email": "client@example.com",
"name": "Jane Smith"
},
"amount": 15000,
"currency": "USD",
"memo": "Payment for services rendered",
"payment_methods": ["card", "ach"],
"payment_terms_type": "net",
"payment_terms_days": 30
}
}'
This creates both the agreement and an associated invoice template in a single API call. The invoice template is linked to the agreement via the invoice_template_id field.
Option 2: Two-Step Process (Create Agreement, Then Create Invoice)
If you need more control or want to create the invoice separately:
Step 1: Create the Agreement
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement",
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner"\
},\
{\
"contact_id": "CLIENT_CONTACT_ID",\
"role": "signer"\
}\
]
}'
Response includes agreement ID:
{
"data": {
"id": "990e8400-e29b-41d4-a716-446655440000",
...
}
}
Step 2: Create Invoice and Link to Agreement
curl -X POST https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"agreement_id": "990e8400-e29b-41d4-a716-446655440000",
"billing_contact": {
"email": "client@example.com",
"name": "Jane Smith"
},
"amount": 15000,
"currency": "USD",
"memo": "Payment for services rendered",
"payment_methods": ["card", "ach"],
"payment_terms_type": "net",
"payment_terms_days": 30
}
}'
When to use each approach:
Option 1 (single request): Use when you want to create the agreement and invoice together atomically. This is simpler and ensures the invoice is always linked to the agreement.
Option 2 (two-step): Use when you need to:
Create the agreement first and review it before adding the invoice
- Create multiple invoices for the same agreement
- Have more control over the invoice creation timing
- Handle errors separately for agreement vs invoice creation
tag/Agreements/Recipient-Roles Recipient Roles
| Role | Description |
|---|---|
owner |
The account holder initiating the agreement. Exactly one recipient must have this role. |
signer |
A recipient who needs to sign the agreement |
viewer |
A recipient who can view but not sign the agreement |
payee |
A recipient who will receive payment (used with invoices) |
tag/Agreements/Field-Values-(Prefilling) Field Values (Prefilling)
You can prefill field values when creating an agreement:
{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement",
"field_values": {
"field_1": "John Doe",
"field_2": "2024-01-01",
"company_name": "Acme Corp"
},
"recipients": [...]
}
Keys in field_values must match field_id values from your template. Fetch the template to list field_names (non-variable fields) and variables (each variable’s field_id and display name):
curl https://api.agree.com/api/v1/agreements/templates/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"
The response includes a field_names array listing all available fields in the template, plus a variables array for template variables (see below). Use each field’s field_id as the key in field_values (for variables, use the field_id from the variables entry, not the display name).
Typed values and rich text
Each entry in field_values can be either:
- A string (legacy): plain text. Works for any field or variable.
- An object with a
contentstring and optionalcontent_type:
{
"content": "<strong>Renewal</strong> 2026-05-01",
"content_type": "html"
}
content(required): the payload.content_type(optional):plaintext,html, ormarkdown. If omitted,plaintextis used.
Rich text applies only to template variables. If the field_values key matches a variablefield_id (from GET /api/v1/agreements/templates/:id → data.variables), then content_type html or markdown is converted into styled inline content in the agreement body (bold, italics, line breaks, HTML lists, markdown list lines with - / *, etc.).
For all non-variable fields (text, date, signature, checkbox, and every other fillable field), typed objects are accepted, but only the plain-text form is stored on the field— formatting is not preserved. Use plain strings for those unless you only need a simple string payload.
Invalid typed objects (for example missing content or an invalid content_type) return 400 Bad Request with an error referencing field_values.
tag/Agreements/Custom-Variables-(Template-Variables) Custom Variables (Template Variables)
Templates can contain custom variables — placeholder fields for dynamic content like names, dates, or amounts. Variables remain as live fields in the agreement until it is sent, at which point they are resolved into plain text.
Variable values can be provided at creation time via field_values, or filled in later through the editor UI. All variables must have values before the agreement can be sent.
Rich text: Only keys that correspond to variables (see variables[].field_id) honor content_type of html or markdown and keep formatting in the document. Other fields always receive plain text only—see Typed values and rich text.
Step 1: Discover Template Variables
Fetch the template to see its variables:
curl https://api.agree.com/api/v1/agreements/templates/TEMPLATE_ID \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Agreement",
"field_names": ["signature_field", "date_field"],
"variables": [\
{\
"name": "Employee Name",\
"field_id": "var_abc123"\
},\
{\
"name": "Start Date",\
"field_id": "var_def456"\
},\
{\
"name": "Salary",\
"field_id": "var_ghi789"\
}\
]
}
}
The variables array lists each custom variable with its name (display label) and field_id (the key to use in field_values).
Step 2: Provide Variable Values (Optional at Creation)
When creating the agreement, you can pre-fill variable values via field_values. Any variables not provided will remain as unfilled live fields in the agreement.
curl -X POST https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Employment Agreement - Jane Smith",
"field_values": {
"var_abc123": "Jane Smith",
"var_def456": "2025-03-01",
"var_ghi789": "$120,000"
},
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner"\
},\
{\
"contact": {\
"email": "jane@example.com",\
"name": "Jane Smith"\
},\
"role": "signer",\
"assigned_fields": ["signature_field", "date_field"]\
}\
]
}'
When the agreement is sent, variable values are resolved into plain text — recipients will see "Jane Smith" rather than a placeholder (rich variable content is flattened at send time).
Rich text examples (variables only)
Plain string (unchanged):
"var_abc123": "Jane Smith"
HTML (lists, emphasis, etc.):
"var_schedule": {
"content_type": "html",
"content": "<ul><li>Payment 1 on 2026-03-17</li><li>Payment 2 on 2026-04-17</li></ul>"
}
Markdown (line breaks, - / * list lines, **bold**, *italic*, _italic_):
"var_schedule": {
"content_type": "markdown",
"content": "- **First** payment on 2026-03-17\n- Second payment on 2026-04-17"
}
Default to plaintext when content_type is omitted:
"var_note": { "content": "Shown as plain text only" }
Error Handling
If you attempt to send an agreement with unfilled variables, the API returns a 400 Bad Request:
{
"error": "Unfilled variables: Employee Name, Start Date. All variables must have values before sending."
}
tag/Agreements/Listing-Agreements Listing Agreements
Retrieve agreements with optional filtering:
# Get all agreements
curl https://api.agree.com/api/v1/agreements \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by status
curl "https://api.agree.com/api/v1/agreements?status=drafted" \
-H "Authorization: Bearer YOUR_API_KEY"
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
page_size |
integer | Items per page (default: 10, max: 100) |
status |
string | Filter by status: created, drafted, sent, signed, executed, terminated |
tag/Agreements/Sending-an-Agreement Sending an Agreement
After creating an agreement, send it to recipients:
curl -X POST https://api.agree.com/api/v1/agreements/990e8400-e29b-41d4-a716-446655440000/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"delivery_mode": "managed"
}'
Delivery Modes:
managed- Agree sends emails to recipients automaticallyembedded- Emails are suppressed (you handle delivery yourself)
tag/Agreements/Create-and-Send-in-One-Step Create and Send in One Step
For convenience, create and send an agreement in a single request:
curl -X POST https://api.agree.com/api/v1/agreements/create_and_send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement",
"delivery_mode": "managed",
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner"\
},\
{\
"contact_id": "CLIENT_CONTACT_ID",\
"role": "signer"\
}\
]
}'
tag/Agreements/Updating-an-Agreement Updating an Agreement
Update agreement details and recipients. You can include field_values inside agreement the same way as on create; rich text (html / markdown) still applies only to template variables—see Typed values and rich text.
curl -X PUT https://api.agree.com/api/v1/agreements/990e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agreement": {
"name": "Updated Service Agreement",
"recipients": [\
{\
"contact_id": "YOUR_CONTACT_ID",\
"role": "owner",\
"assigned_fields": ["company_address"]\
},\
{\
"contact_id": "CLIENT_CONTACT_ID",\
"role": "signer",\
"assigned_fields": ["signature_field"]\
}\
]
}
}'
Note: Updating recipients replaces all existing recipients. Make sure to include all recipients you want to keep.
tag/Agreements/Agreement-Statuses Agreement Statuses
| Status | Description |
|---|---|
created |
Agreement created but not yet finalized |
drafted |
Agreement is in draft state (default when created) |
sent |
Agreement has been sent to recipients |
viewed |
At least one recipient has viewed the agreement |
signed |
At least one recipient has signed |
executed |
Agreement is fully executed (all required signatures collected) |
renewed |
Agreement has been renewed |
terminated |
Agreement has been terminated |
tag/Agreements/Fields-Reference Fields Reference
Core Fields
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique agreement identifier |
name |
string | Agreement name |
status |
string | Current status (see statuses above) |
template_id |
UUID | Template used to create this agreement |
organization_id |
UUID | Your organization's ID |
invoice_template_id |
UUID | Associated invoice template (if invoice was created) |
Recipient Fields
| Field | Type | Description |
|---|---|---|
recipients |
array | List of recipients with their roles and assigned fields |
signing_order |
array | List of recipient IDs in signing order (if enabled) |
signing_order_enabled |
boolean | Whether signing order is enforced |
Delivery Fields
| Field | Type | Description |
|---|---|---|
delivery_mode |
string | embedded or managed |
reminder_schedule |
string | none, daily, weekly, or monthly |
reminder_scheduled_at |
datetime | When the next reminder will be sent |
Date Fields
| Field | Type | Description |
|---|---|---|
starts_at |
datetime | When the agreement starts |
ends_at |
datetime | When the agreement ends |
executed_at |
datetime | When the agreement was fully executed |
last_reminder_sent_at |
datetime | When the last reminder was sent |
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.pdf Download agreement PDF
Returns a presigned URL to download the agreement PDF for the current revision (same source as the Agree app document menu).
If the PDF is not in storage yet or is stale vs. the revision, the server first waits briefly in case another request already
kicked off generation, then may enqueue SSR rendering and waits up to a short inline budget
(default 5 seconds, invoice_pdf_api_inline_wait_ms). If the file is still not ready, responds
with 202 Accepted, a Retry-After header (default 3 seconds, invoice_pdf_api_retry_after_seconds),
and data.status: "pending". Repeat the same GET until you receive 200 with data.url.
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Responses
200
Presigned download URL
202
PDF not ready; retry after Retry-After
400
Bad request
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/agreements/{id}/pdf
https://secure.agree.com/api/v1/agreements/{id}/pdf
Response samples
- 200
- 202
- 400
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"expires_in": 0,
"url": "http://example.com"
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.send Send agreement
Sends an agreement to its recipients. Updates the agreement status to 'sent' and sends emails if delivery_mode is 'managed'.
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Request Body schema: application/json optional
Send params
| delivery_method | string Value:"email" Delivery method (only valid for managed mode) |
| delivery_mode required |
string Enum:"embedded""managed" Delivery mode: 'embedded' (emails suppressed) or 'managed' (Agree sends emails) |
| message | string or null Optional message to include in email (only valid for managed mode) |
| reminder_schedule | string or null Enum:"none""daily""weekly""monthly" Reminder schedule override (only valid for managed mode) |
Responses
200
Agreement sent
400
Bad request
401
Unauthorized
403
Forbidden
404
Not found
post/api/v1/agreements/{id}/send
https://secure.agree.com/api/v1/agreements/{id}/send
Request samples
- Payload
Content type
application/json
Copy
`{"delivery_method": "email",
"delivery_mode": "managed",
"message": "Please review and sign this agreement",
"reminder_schedule": "weekly"
}`
Response samples
- 200
- 400
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signers": [{"assigned_fields": ["signature_field",
"date_field"
],
"contact_id": "770e8400-e29b-41d4-a716-446655440000",
"role": "signer",
"signing_link": "https://example.com/sign/abc123token",\
"status": "pending"
}
],
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.create_and_send Create and send agreement
Convenience endpoint that creates an agreement from a template and sends it immediately.
Combines create and send operations in a single request.
Authorizations:
bearer
Request Body schema: application/json optional
Create and send params
| delivery_mode | string Enum:"embedded""managed" Delivery mode: 'embedded' (emails suppressed) or 'managed' (Agree sends emails) |
| ends_at | string or null When the agreement ends (ISO8601 format) |
| field_values | object Map of field_id to value for prefilling fields and template variables. Values can be a legacy string or a typed rich text object. If content_type is omitted in object form, plaintext is used by default. |
| invoice | object or null Invoice to create with this agreement. Creates an invoice template associated with the agreement. Either billing_contact or contact_id is required when providing an invoice.Either amount/currency or line_items is required (if line_items are provided, amount is calculated from them).IMPORTANT: amount and unit_price.amount are INTEGERS in the smallest currency unit (cents for USD), NOT dollars. A $150 invoice is amount: 15000. Multiply dollar amounts by 100. |
| name required |
string Agreement name |
| payments_enabled | boolean Whether payments are enabled for this agreement |
| recipients | Array of objects List of recipients with their assigned fields. Important: Exactly one recipient must have the owner role. This must be the account holder (the person whose API key is being used). Use GET /api/v1/contacts to find your Contact ID.Each recipient must provide either contact_id or contact (but not both).- contact_id: Reference an existing contact- contact: Create or update a contact with email and name (required), and optionally company and titleUse assigned_fields to assign specific fields (by field name) to each recipient. Fields not assigned will default to the owner recipient. |
| reminder_schedule | string or null Enum:"none""daily""weekly""monthly" Reminder schedule frequency (only valid for managed mode) |
| signing_order | Array of strings List of contact IDs in signing order |
| signing_order_enabled | boolean Whether signing order is enabled |
| starts_at | string or null When the agreement starts (ISO8601 format) |
| template_id required |
string Template ID to create agreement from (required) |
Responses
201
Agreement created and sent
401
Unauthorized
404
Template not found
422
Validation errors
post/api/v1/agreements/create_and_send
https://secure.agree.com/api/v1/agreements/create\_and\_send
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"delivery_mode": "managed",
"field_values": {"field_1": "John Doe",
"field_2": {"content": "MSA for Acme Corp",
"content_type": "markdown"
}
},
"invoice": {"amount": 15000,
"billing_contact": {"email": "billing@example.com",
"name": "Billing Contact"
},
"currency": "USD",
"memo": "Payment for services",
"payment_direction": "receivable",
"payment_methods": ["card",
"ach"
],
"payment_terms_days": 30,
"payment_terms_type": "net"
},
"name": "Service Agreement",
"payments_enabled": false,
"recipients": [{"assigned_fields": ["company_address",
"date"
],
"contact_id": "770e8400-e29b-41d4-a716-446655440000",
"role": "owner"
},
{"assigned_fields": ["signature_field",
"date_field"
],
"contact": {"company": "Example Corp",
"email": "newrecipient@example.com",
"name": "Jane Doe",
"title": "CEO"
},
"role": "signer"
}
],
"reminder_schedule": "weekly",
"signing_order_enabled": false,
"template_id": "550e8400-e29b-41d4-a716-446655440000"
}`
Response samples
- 201
- 401
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.templates List agreement templates
Returns a list of agreement templates for the authenticated organization with field names.
Authorizations:
bearer
Responses
200
Templates list
401
Unauthorized
get/api/v1/agreements/templates
https://secure.agree.com/api/v1/agreements/templates
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{"field_names": ["signature_field",
"date_field",
"name_field"
],
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement Template"
}
]
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.index List agreements
Returns a paginated list of agreements for the authenticated organization.
Authorizations:
bearer
query Parameters
| page | integer Page number (default: 1) |
| page_size | integer Items per page (default: 10) |
Responses
200
Agreements list
400
Bad Request
401
Unauthorized
get/api/v1/agreements
https://secure.agree.com/api/v1/agreements
Response samples
- 200
- 400
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",\
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",\
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signers": [{"assigned_fields": ["signature_field",
"date_field"
],
"contact_id": "770e8400-e29b-41d4-a716-446655440000",
"role": "signer",
"signing_link": "https://example.com/sign/abc123token",\
"status": "pending"
}
],
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
],
"pagination": {"page": 0,
"page_size": 0,
"total_entries": 0,
"total_pages": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.create Create agreement from template
Creates a new agreement from a template for the authenticated organization.
The agreement will be created with status 'drafted' by default. Requires a template_id and supports prefilling fields via field_values mapping.
Important: Exactly one recipient must have the owner role. This must be the account holder (the person whose API key is being used). The account holder is also a contact - use GET /api/v1/contacts to find your Contact ID.
For each recipient, you can optionally provide either:
contact_idto reference an existing contactcontactwithemailandname(and optionallycompanyandtitle) to automatically create or update a contact
Both will set the recipient's contact automatically. You cannot provide both for the same recipient.
Template recipients and fields: Parties (recipients) from the template are copied onto the new agreement, and each field keeps the same assignment as on the template (matched by contact). Request recipients can add more parties or update roles for contacts you include.
assigned_fields: Optional per-recipient list of template field ids/names. When provided, only those fields are reassigned to that recipient; all other fields keep their template assignments (they do not fall back to the owner).
field_values: Prefills values in the document without changing who each field is assigned to.
Authorizations:
bearer
Request Body schema: application/json optional
Agreement create params
Responses
201
Agreement created
401
Unauthorized
404
Template not found
422
Validation errors
post/api/v1/agreements
https://secure.agree.com/api/v1/agreements
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"delivery_mode": "managed",
"field_values": {"field_1": "John Doe",
"field_2": {"content": "MSA for Acme Corp",
"content_type": "markdown"
}
},
"invoice": {"amount": 15000,
"billing_contact": {"email": "billing@example.com",
"name": "Billing Contact"
},
"currency": "USD",
"memo": "Payment for services",
"payment_direction": "receivable",
"payment_methods": ["card",
"ach"
],
"payment_terms_days": 30,
"payment_terms_type": "net"
},
"name": "Service Agreement",
"payments_enabled": false,
"reminder_schedule": "weekly",
"signing_order_enabled": false,
"template_id": "550e8400-e29b-41d4-a716-446655440000"
}`
Response samples
- 201
- 401
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.show_template Get template
Returns a single template by ID with field names.
Authorizations:
bearer
path Parameters
| id required |
string Template ID (UUID) |
Responses
200
Template
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/agreements/templates/{id}
https://secure.agree.com/api/v1/agreements/templates/{id}
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"field_names": ["signature_field",
"date_field",
"name_field"
],
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Service Agreement Template"
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.delete Delete agreement
Deletes an agreement by ID (soft delete).
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Responses
204
Agreement deleted
401
Unauthorized
403
Forbidden
404
Not found
delete/api/v1/agreements/{id}
https://secure.agree.com/api/v1/agreements/{id}
Response samples
- 401
- 403
- 404
Content type
application/json
Copy
`{"error": "Invalid or missing API key"
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.show Get agreement
Returns a single agreement by ID.
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Responses
200
Agreement
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/agreements/{id}
https://secure.agree.com/api/v1/agreements/{id}
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.update (2) Update agreement
Updates an existing agreement.
The following fields cannot be updated directly:
- deleted_at
- executed_at
- organization_id
- preview_url
- status
- version
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Request Body schema: application/json optional
Agreement params
| agreement required |
object |
Responses
200
Agreement updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
patch/api/v1/agreements/{id}
https://secure.agree.com/api/v1/agreements/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"agreement": {"ends_at": "2024-12-31T23:59:59Z",
"forward_signature_enabled": true,
"name": "Service Agreement",
"payments_enabled": false,
"recipients": [{"contact_id": "770e8400-e29b-41d4-a716-446655440000",
"role": "signer"
},
{"contact": {"company": "Example Corp",
"email": "newrecipient@example.com",
"name": "Jane Doe",
"title": "CEO"
},
"role": "viewer"
}
],
"reminder_schedule": "weekly",
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.update Update agreement
Updates an existing agreement.
The following fields cannot be updated directly:
- deleted_at
- executed_at
- organization_id
- preview_url
- status
- version
Authorizations:
bearer
path Parameters
| id required |
string Agreement ID (UUID) |
Request Body schema: application/json optional
Agreement params
| agreement required |
object |
Responses
200
Agreement updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
put/api/v1/agreements/{id}
https://secure.agree.com/api/v1/agreements/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"agreement": {"ends_at": "2024-12-31T23:59:59Z",
"forward_signature_enabled": true,
"name": "Service Agreement",
"payments_enabled": false,
"reminder_schedule": "weekly",
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"current_signing_order": 0,
"deleted_at": null,
"delivery_mode": "managed",
"docs_url": "https://secure.agree.com/docs/550e8400-e29b-41d4-a716-446655440000",
"ends_at": "2024-12-31T23:59:59Z",
"executed_at": null,
"forward_signature_enabled": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"invoice_template_id": null,
"last_reminder_sent_at": null,
"name": "Service Agreement",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"payments_enabled": false,
"preview_url": "https://example.com/preview/550e8400",
"reminder_schedule": "weekly",
"reminder_scheduled_at": "2024-01-22T10:00:00Z",
"share_url": null,
"signing_order": [ ],
"signing_order_enabled": false,
"starts_at": "2024-01-01T00:00:00Z",
"status": "drafted",
"version": 0
}
}`
tag/Invoices Invoices
Create, send, and track payment requests to your customers.
tag/Invoices/Overview Overview
Invoices are the core of Agree's payment system. An invoice represents a request for payment that you send to a customer. When created, Agree generates a secure payment link that your customer can use to pay via their preferred method.
Key concepts:
- Invoices are sent to contacts (customers in your address book)
- Each invoice supports multiple payment methods: ACH bank transfer, credit card, or wire transfer
- Invoices can be one-time or recurring on a schedule
- Automatic email delivery sends the payment link to your customer
- Webhooks notify you in real-time when payment status changes
tag/Invoices/Common-Use-Cases Common Use Cases
Bill a Client for a Completed Project
Send a one-time invoice after completing work:
curl -X POST https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "client@company.com",
"name": "Sarah Johnson",
"company": "Johnson & Co"
},
"amount": {"amount": 500000, "currency": "USD"},
"payment_methods": ["card", "ach", "wire"],
"due_at": "2025-02-01T00:00:00Z",
"memo": "Website redesign project - Final payment"
}
}'
The client receives an email with a payment link. You'll get a webhook when they pay.
Set Up Monthly Retainer Billing
Create a recurring invoice that bills automatically each month:
curl -X POST https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "accounting@bigcorp.com",
"name": "Accounts Payable",
"company": "BigCorp Inc"
},
"amount": {"amount": 250000, "currency": "USD"},
"payment_methods": ["ach"],
"memo": "Monthly consulting retainer",
"recurring_options": {
"schedule": "custom",
"repeat_frequency": 1,
"repeat_unit": "month",
"repeat_on_type": "day_of_month",
"repeat_on_day": 1,
"recurring_end_type": "never",
"reminder_schedule": "weekly"
}
}
}'
Agree automatically generates and sends invoices on the 1st of each month.
Track Outstanding Invoices
Find all unpaid invoices that are past due:
curl "https://api.agree.com/api/v1/invoices?statuses=sent,due&date_type=due_at&date_end=2025-01-17" \
-H "Authorization: Bearer YOUR_API_KEY"
Handle Failed Payments
When a payment fails, you receive an invoice.failed webhook. The invoice status changes to failed, but the customer can retry payment using the same link. To check failed invoices:
curl "https://api.agree.com/api/v1/invoices?statuses=failed" \
-H "Authorization: Bearer YOUR_API_KEY"
Generate a Revenue Report
Get all paid invoices for a specific month:
curl "https://api.agree.com/api/v1/invoices?statuses=paid&date_type=paid_at&date_start=2025-01-01&date_end=2025-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"
tag/Invoices/Creating-an-Invoice Creating an Invoice
Here's a basic invoice creation:
curl -X POST https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "customer@example.com",
"name": "John Doe",
"company": "Acme Corp"
},
"amount": {"amount": 15000, "currency": "USD"},
"payment_methods": ["card", "ach"],
"due_at": "2025-02-15T00:00:00Z",
"scheduled_at": "2025-02-01T00:00:00Z",
"memo": "Website development - Phase 1"
}
}'
Note: When using the create endpoint, due_at and scheduled_at are required fields. The invoice issue date (inserted_at) is automatically set when the invoice is created. All dates should be in ISO8601 format (UTC).
Response:
{
"data": {
"id": "4a755746-ba45-4226-a669-aebc7ad3719c",
"status": "sent",
"amount": {"amount": 15000, "currency": "USD"},
"billing_contact": {
"email": "customer@example.com",
"name": "John Doe",
"company": "Acme Corp",
"title": null
},
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card", "ach"],
"due_at": "2025-02-15T00:00:00Z",
"scheduled_at": "2025-02-01T00:00:00Z",
"memo": "Website development - Phase 1",
"inserted_at": "2025-01-15T10:30:00Z"
}
}
The payment_link is a secure URL you can share with your customer. When automatic_delivery is enabled (the default), Agree emails this link to the billing contact automatically.
Create and Send in One Step
For convenience, you can create and send an invoice in a single API call:
curl -X POST https://api.agree.com/api/v1/invoices/create_and_send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "customer@example.com",
"name": "John Doe"
},
"amount": {"amount": 15000, "currency": "USD"},
"payment_methods": ["card", "ach"],
"memo": "Website development - Phase 1"
}
}'
Note: When using create_and_send, scheduled_at is always set to the current UTC time (to send immediately), regardless of any value you provide. If due_at is not provided, it will default to the current UTC time. The invoice issue date (inserted_at) is automatically set when the invoice is created. You can optionally specify a custom due_at:
curl -X POST https://api.agree.com/api/v1/invoices/create_and_send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {
"email": "customer@example.com",
"name": "John Doe"
},
"amount": {"amount": 15000, "currency": "USD"},
"payment_methods": ["card", "ach"],
"due_at": "2025-02-15T00:00:00Z",
"memo": "Website development - Phase 1"
}
}'
Note that scheduled_at is always set to the current UTC time when using create_and_send, so it's not necessary (and will be ignored) if provided.
Response:
{
"data": {
"id": "4a755746-ba45-4226-a669-aebc7ad3719c",
"status": "sending",
"amount": {"amount": 15000, "currency": "USD"},
...
}
}
The response includes status: "sending" to indicate the invoice is being sent asynchronously. The invoice will transition to sent once the email is delivered.
When to use create_and_send:
- You want to create and send an invoice immediately in one request
- You don't need to review or modify the invoice before sending
- You want to simplify your integration by combining two operations
When to use create + send separately:
- You need to review the invoice before sending
- You want to add additional information after creation
- You're creating invoices in bulk and want to send them later
Amounts
Amounts are specified in the smallest currency unit. For USD, this means cents:
| You want to charge | Send this amount |
|---|---|
| $100.00 | 10000 |
| $1,500.50 | 150050 |
| $0.99 | 99 |
{
"amount": {
"amount": 10000,
"currency": "USD"
}
}
Specifying the Customer
You can specify who receives the invoice in two ways:
Using billing_contact (recommended for new customers):
{
"invoice": {
"billing_contact": {
"email": "customer@example.com",
"name": "John Doe"
}
}
}
This creates or updates a contact automatically.
Using contact_id (for existing contacts):
{
"invoice": {
"contact_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
You cannot use both in the same request.
tag/Invoices/Invoice-Lifecycle Invoice Lifecycle
Every invoice progresses through a series of statuses:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ created │ ──► │ sent │ ──► │ due │ ──► │ paid │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│
├──► processing ──► paid
│ │
│ └──► failed
│
└──► canceled
| Status | Description |
|---|---|
created |
Invoice created but not yet sent to customer |
sending |
Invoice is being sent (temporary status returned by API) |
sent |
Invoice emailed to customer, awaiting payment |
due |
Invoice is past the scheduled send date |
processing |
Payment initiated, waiting for confirmation |
paid |
Payment completed successfully |
failed |
Payment attempt failed (customer can retry) |
canceled |
Invoice was canceled (no payment expected) |
refunded |
Payment was refunded after completion |
draft |
Template-only, not yet converted to invoice |
Note: The sending status is a temporary status returned by the API when you use create_and_send or send endpoints. It indicates the invoice is being sent asynchronously. When you query the invoice later, it will show sent (or due if sent immediately with a past due date).
tag/Invoices/Recurring-Invoices Recurring Invoices
Set up automatic recurring invoices by providing recurring_options:
curl -X POST https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"billing_contact": {"email": "customer@example.com"},
"amount": {"amount": 99900, "currency": "USD"},
"payment_methods": ["card"],
"recurring_options": {
"schedule": "custom",
"repeat_frequency": 1,
"repeat_unit": "month",
"recurring_end_type": "never",
"reminder_schedule": "weekly"
}
}
}'
Recurring Options
| Field | Type | Description |
|---|---|---|
schedule |
string | none (one-time) or custom (recurring) |
repeat_frequency |
integer | How often to repeat (e.g., 1 = every period, 2 = every other) |
repeat_unit |
string | week or month |
repeat_on_weekday |
string | For weekly: monday, tuesday, etc. |
repeat_on_type |
string | For monthly: day_of_month or day_of_week |
repeat_on_day |
integer | Day of month (1-31) |
repeat_on_week |
integer | Week of month (1-5, where 5 = last) |
recurring_end_type |
string | never, date, or count |
recurring_end_date |
datetime | End date (when type is date) |
recurring_end_count |
integer | Number of occurrences (when type is count) |
reminder_schedule |
string | none, daily, weekly, or monthly |
forward_payment_enabled |
boolean | Allow paying future invoices early |
pass_on_fees_enabled |
boolean | Pass processing fees to the payer at checkout (default: false) |
Examples
Monthly on the 15th, forever:
{
"schedule": "custom",
"repeat_frequency": 1,
"repeat_unit": "month",
"repeat_on_type": "day_of_month",
"repeat_on_day": 15,
"recurring_end_type": "never"
}
Every 2 weeks on Monday, for 6 occurrences:
{
"schedule": "custom",
"repeat_frequency": 2,
"repeat_unit": "week",
"repeat_on_weekday": "monday",
"recurring_end_type": "count",
"recurring_end_count": 6
}
tag/Invoices/Listing-and-Filtering-Invoices Listing and Filtering Invoices
Retrieve invoices with powerful filtering options:
# Get all invoices
curl https://api.agree.com/api/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by status
curl "https://api.agree.com/api/v1/invoices?statuses=sent,due" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by date range (invoices due in January 2025)
curl "https://api.agree.com/api/v1/invoices?date_type=due_at&date_start=2025-01-01&date_end=2025-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by amount range ($100-$500)
curl "https://api.agree.com/api/v1/invoices?amount_min=100&amount_max=500" \
-H "Authorization: Bearer YOUR_API_KEY"
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
page_size |
integer | Items per page (default: 10, max: 100) |
statuses |
string | Comma-separated status filter |
date_start |
string | Start date (YYYY-MM-DD) |
date_end |
string | End date (YYYY-MM-DD) |
date_type |
string | Which date to filter: paid_at, due_at, scheduled_at |
date_timezone |
string | Timezone for dates (default: Etc/UTC) |
amount_min |
number | Minimum amount in dollars |
amount_max |
number | Maximum amount in dollars |
customer |
string | Filter by customer/company name |
include_drafts |
boolean | Include draft invoices |
tag/Invoices/Sending-an-Invoice Sending an Invoice
If you created an invoice without sending it (or want to resend), you can send it explicitly:
curl -X POST https://api.agree.com/api/v1/invoices/4a755746-ba45-4226-a669-aebc7ad3719c/send \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"data": {
"id": "4a755746-ba45-4226-a669-aebc7ad3719c",
"status": "sending",
...
}
}
Note: You can only send invoices that are in created status. Invoices that are already sent, due, or paid cannot be resent using this endpoint.
tag/Invoices/Updating-an-Invoice Updating an Invoice
Update invoice details before payment:
curl -X PUT https://api.agree.com/api/v1/invoices/4a755746-ba45-4226-a669-aebc7ad3719c \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"invoice": {
"memo": "Updated memo - Website development Phase 1",
"due_at": "2025-02-28T00:00:00Z"
}
}'
Note: Some fields cannot be changed after certain status transitions (e.g., you can't change the amount after payment processing begins).
tag/Invoices/Downloading-invoice-and-receipt-PDFs Downloading invoice and receipt PDFs
These endpoints return a presigned S3 URL in JSON (not the raw PDF bytes). The URL is valid for one hour (expires_in: 3600). Use a GET to the returned url to download the file (e.g. redirect the user or fetch server-side).
Invoice PDF
curl "https://api.agree.com/api/v1/invoices/INVOICE_ID/pdf" \
-H "Authorization: Bearer YOUR_API_KEY"
Response (200):
{
"data": {
"url": "https://...",
"expires_in": 3600
}
}
If the PDF is not in storage yet, the API waits a short time (default 5 seconds of server-side polling, configurable via invoice_pdf_api_inline_wait_ms) for the file to appear—first in case another client already started generation, then after enqueueing generation if needed. If it is still not ready, you receive 202 Accepted with a Retry-After header (default 3 seconds, invoice_pdf_api_retry_after_seconds) and a JSON body such as data: { "status": "pending", "retry_after_seconds": 3, ... }. Repeat the same GET until you get 200 with data.url. This avoids holding many long-lived HTTP connections when PDFs are slow or the render queue is busy.
Receipt PDF
Only available when the invoice status is paid. Otherwise the API returns 422.
curl "https://api.agree.com/api/v1/invoices/INVOICE_ID/receipt_pdf" \
-H "Authorization: Bearer YOUR_API_KEY"
Response (200): Same shape as invoice PDF (data.url, data.expires_in).
If the invoice is paid but the receipt file is not available yet, the API returns 404.
tag/Invoices/Canceling-an-Invoice Canceling an Invoice
Cancel an unpaid invoice:
curl -X DELETE https://api.agree.com/api/v1/invoices/4a755746-ba45-4226-a669-aebc7ad3719c \
-H "Authorization: Bearer YOUR_API_KEY"
tag/Invoices/Fields-Reference Fields Reference
Core Fields
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique invoice identifier |
name |
string | Invoice display name |
status |
string | Current status (see lifecycle) |
amount |
object | Amount with amount (cents) and currency |
memo |
string | Notes visible to customer (max 255 chars) |
organization_id |
UUID | Your organization's ID |
agreement_id |
UUID | Associated agreement (if any) |
Customer Fields
| Field | Type | Description |
|---|---|---|
billing_contact |
object | Customer info: email, name, company, title |
payment_link |
string | URL where customer can pay |
Payment Fields
| Field | Type | Description |
|---|---|---|
payment_methods |
array | Accepted methods: ach, card, wire |
payment_type |
string | invoice, payment, or subscription |
used_payment_method |
string | Method used for successful payment |
sales_tax_percentage |
number | Tax percentage applied |
Date Fields
| Field | Type | Description |
|---|---|---|
scheduled_at |
datetime | When invoice will be/was sent |
sent_at |
datetime | When invoice was emailed |
due_at |
datetime | Payment due date |
paid_at |
datetime | When payment completed |
processing_at |
datetime | When processing started |
authorized_at |
datetime | When payment was authorized |
inserted_at |
datetime | When invoice was created |
Delivery Fields
| Field | Type | Description |
|---|---|---|
delivery_method |
string | How invoice is delivered (email) |
automatic_delivery |
boolean | Auto-send when created |
Recurring Fields
| Field | Type | Description |
|---|---|---|
recurring_options |
object | Recurring schedule configuration |
recurring_sequence |
integer | Position in recurring series (1, 2, 3...) |
Reminder Fields
| Field | Type | Description |
|---|---|---|
reminder_scheduled_at |
datetime | Next reminder date |
last_reminder_sent_at |
datetime | Last reminder sent |
External Reference Fields
| Field | Type | Description |
|---|---|---|
external_id |
string | Your external invoice ID |
external_customer_id |
string | Your external customer ID |
destination_organization_id |
UUID | For B2B: receiving organization |
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.receipt_pdf Download receipt PDF
Returns a presigned URL to download the payment receipt PDF for a paid invoice (same as the Agree app invoice menu). Returns 422 if the invoice is not paid.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Responses
200
Presigned download URL
400
Bad request
401
Unauthorized
403
Forbidden
404
Receipt PDF not found
422
Invoice not paid
get/api/v1/invoices/{id}/receipt_pdf
https://secure.agree.com/api/v1/invoices/{id}/receipt\_pdf
Response samples
- 200
- 400
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"expires_in": 0,
"url": "http://example.com"
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.mark_as_sent Mark invoice as sent
Marks an invoice as sent with optional sent date.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Request Body schema: application/json optional
Mark as sent params
| sent_at | string Date when invoice was sent (ISO8601 format: YYYY-MM-DD). Defaults to today. |
Responses
200
Invoice marked as sent
401
Unauthorized
403
Forbidden
404
Not found
post/api/v1/invoices/{id}/mark_as_sent
https://secure.agree.com/api/v1/invoices/{id}/mark\_as\_sent
Request samples
- Payload
Content type
application/json
Copy
`{"sent_at": "2019-08-24"
}`
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.send Send invoice
Sends an invoice to its recipient. Schedules the invoice for sending via the invoice scheduler, which will send email notifications to the recipient.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Responses
200
Invoice sent
400
Bad request
401
Unauthorized
403
Forbidden
404
Not found
post/api/v1/invoices/{id}/send
https://secure.agree.com/api/v1/invoices/{id}/send
Response samples
- 200
- 400
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.index List invoices
Returns a paginated list of invoices for the authenticated organization.
Authorizations:
bearer
query Parameters
| page | integer Page number (default: 1) |
| page_size | integer Items per page (default: 10) |
| date_start | string Start date for filtering (ISO8601 format: YYYY-MM-DD) |
| date_end | string End date for filtering (ISO8601 format: YYYY-MM-DD) |
| date_type | string Date field to filter by. Valid values: paid_at, due_at, scheduled_at (default: scheduled_at) |
| date_timezone | string Timezone for date filtering (default: Etc/UTC) |
| statuses | string Filter by invoice statuses (comma-separated). Valid values: created, due, sent, canceled, paid, failed, refunded, draft |
| amount_min | number Minimum invoice amount (in dollars) |
| amount_max | number Maximum invoice amount (in dollars) |
| customer | string Filter by customer/company name (fuzzy search) |
| include_drafts | boolean Include draft invoices (invoice templates without invoices) |
Responses
200
Invoices list
401
Unauthorized
get/api/v1/invoices
https://secure.agree.com/api/v1/invoices
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",\
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",\
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",\
"used_payment_method": null
}
],
"pagination": {"page": 0,
"page_size": 0,
"total_entries": 0,
"total_pages": 0
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.create Create invoice
Creates a new invoice for the authenticated organization.
Amounts are integers in the smallest currency unit (cents for USD), NOT dollars. A $150 invoice is {"amount": 15000, "currency": "USD"}. Multiply dollar amounts by 100.
Required fields:
due_at- Payment due date (ISO8601 format, UTC)scheduled_at- When to send the invoice (ISO8601 format, UTC)
You can optionally provide:
recurring_optionsto configure recurring settings. If not provided, the invoice will have no recurring schedule (schedule: "none").
You can optionally provide either:
billing_contactwithemailandname(and optionallycompanyandtitle) to automatically create or update a contactcontact_idto reference an existing contact
Both will set the invoice's billing_contact automatically. You cannot provide both.
Authorizations:
bearer
Request Body schema: application/json optional
Invoice params
| invoice required |
object |
Responses
201
Invoice created
401
Unauthorized
422
Validation errors
post/api/v1/invoices
https://secure.agree.com/api/v1/invoices
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"invoice": {"amount": {"amount": 15000,
"currency": "USD"
},
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith"
},
"due_at": "2025-02-15T00:00:00Z",
"memo": "Consulting services - January 2025",
"payment_methods": ["card",
"ach"
],
"recurring_options": {"recurring_end_type": "never",
"repeat_frequency": 1,
"repeat_unit": "month",
"schedule": "custom"
},
"scheduled_at": "2025-02-01T00:00:00Z"
}
}`
Response samples
- 201
- 401
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.pdf Download invoice PDF
Returns a presigned URL to download the invoice PDF (same source as the Agree app invoice menu).
If the PDF is not in storage yet, the server first waits briefly in case another request already
kicked off generation, then may enqueue generation and waits up to a short inline budget
(default 5 seconds, invoice_pdf_api_inline_wait_ms). If the file is still not ready, responds
with 202 Accepted, a Retry-After header (default 3 seconds, invoice_pdf_api_retry_after_seconds),
and data.status: "pending". Repeat the same GET until you receive 200 with data.url.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Responses
200
Presigned download URL
202
PDF not ready; retry after Retry-After
400
Bad request
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/invoices/{id}/pdf
https://secure.agree.com/api/v1/invoices/{id}/pdf
Response samples
- 200
- 202
- 400
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"expires_in": 0,
"url": "http://example.com"
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.delete Delete invoice
Deletes an invoice by ID.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Responses
204
Invoice deleted
401
Unauthorized
403
Forbidden
404
Not found
delete/api/v1/invoices/{id}
https://secure.agree.com/api/v1/invoices/{id}
Response samples
- 401
- 403
- 404
Content type
application/json
Copy
`{"error": "Invalid or missing API key"
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.show Get invoice
Returns a single invoice by ID.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Responses
200
Invoice
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/invoices/{id}
https://secure.agree.com/api/v1/invoices/{id}
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.update (2) Update invoice
Updates an existing invoice.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Request Body schema: application/json optional
Invoice params
| invoice required |
object |
Responses
200
Invoice updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
patch/api/v1/invoices/{id}
https://secure.agree.com/api/v1/invoices/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"invoice": {"amount": {"amount": 15000,
"currency": "USD"
},
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith"
},
"due_at": "2025-02-15T00:00:00Z",
"memo": "Consulting services - January 2025",
"payment_methods": ["card",
"ach"
],
"recurring_options": {"recurring_end_type": "never",
"repeat_frequency": 1,
"repeat_unit": "month",
"schedule": "custom"
},
"scheduled_at": "2025-02-01T00:00:00Z"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.update Update invoice
Updates an existing invoice.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Request Body schema: application/json optional
Invoice params
| invoice required |
object |
Responses
200
Invoice updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
put/api/v1/invoices/{id}
https://secure.agree.com/api/v1/invoices/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"invoice": {"amount": {"amount": 15000,
"currency": "USD"
},
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith"
},
"due_at": "2025-02-15T00:00:00Z",
"memo": "Consulting services - January 2025",
"payment_methods": ["card",
"ach"
],
"recurring_options": {"recurring_end_type": "never",
"repeat_frequency": 1,
"repeat_unit": "month",
"schedule": "custom"
},
"scheduled_at": "2025-02-01T00:00:00Z"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.create_and_send Create and send invoice
Convenience endpoint that creates an invoice and sends it immediately.
Combines create and send operations in a single request. The invoice will be scheduled for sending via the invoice scheduler, which will send email notifications to the recipient.
Authorizations:
bearer
Request Body schema: application/json optional
Invoice params
| invoice required |
object |
Responses
201
Invoice created and sent
401
Unauthorized
422
Validation errors
post/api/v1/invoices/create_and_send
https://secure.agree.com/api/v1/invoices/create\_and\_send
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"invoice": {"amount": {"amount": 15000,
"currency": "USD"
},
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith"
},
"due_at": "2025-02-15T00:00:00Z",
"memo": "Consulting services - January 2025",
"payment_methods": ["card",
"ach"
],
"recurring_options": {"recurring_end_type": "never",
"repeat_frequency": 1,
"repeat_unit": "month",
"schedule": "custom"
},
"scheduled_at": "2025-02-01T00:00:00Z"
}
}`
Response samples
- 201
- 401
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.mark_as_paid Mark invoice as paid
Marks an invoice as paid with optional paid date and payment method.
Authorizations:
bearer
path Parameters
| id required |
string Invoice ID (UUID) |
Request Body schema: application/json optional
Mark as paid params
| paid_at | string Date when invoice was paid (ISO8601 format: YYYY-MM-DD). Defaults to today. |
| payment_method | string Enum:"manual""ach""card""wire" Payment method used (default: manual) |
Responses
200
Invoice marked as paid
401
Unauthorized
403
Forbidden
404
Not found
post/api/v1/invoices/{id}/mark_as_paid
https://secure.agree.com/api/v1/invoices/{id}/mark\_as\_paid
Request samples
- Payload
Content type
application/json
Copy
`{"paid_at": "2019-08-24",
"payment_method": "manual"
}`
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"agreement_id": null,
"amount": {"amount": 15000,
"currency": "USD"
},
"authorized_at": null,
"automatic_delivery": true,
"billing_contact": {"company": "Acme Corporation",
"email": "jane@acme.com",
"name": "Jane Smith",
"title": "CFO"
},
"delivery_method": "email",
"destination_organization_id": null,
"due_at": "2025-02-15T00:00:00Z",
"external_customer_id": null,
"external_id": null,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-10T14:30:00Z",
"invoice_url": "https://secure.agree.com/invoices?modal=invoice-details&invoiceId=550e8400-e29b-41d4-a716-446655440000",
"last_reminder_sent_at": null,
"memo": "Consulting services - January 2025",
"name": "Invoice #1042",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"paid_at": null,
"payment_link": "https://agree.com/pay/abc123token",
"payment_methods": ["card",
"ach"
],
"payment_type": "invoice",
"processing_at": null,
"recurring_options": {"forward_payment_enabled": true,
"recurring_end_type": "never",
"reminder_schedule": "weekly",
"repeat_frequency": 1,
"repeat_on_day": 15,
"repeat_on_type": "day_of_month",
"repeat_unit": "month",
"schedule": "custom"
},
"recurring_sequence": 1,
"reminder_scheduled_at": "2025-01-22T09:00:00Z",
"reviewed_at": "2025-01-10T14:30:00Z",
"sales_tax_percentage": null,
"scheduled_at": "2025-01-15T09:00:00Z",
"sent_at": "2025-01-15T09:00:05Z",
"status": "sent",
"subscription_url": "https://secure.agree.com/subscriptions?modal=subscription-details&subscriptionId=70f2e8c2-0bc2-4f4f-8f9a-adab66f0320a",
"used_payment_method": null
}
}`
tag/Contacts Contacts
Manage your organization's contacts - the people and companies you do business with.
tag/Contacts/Overview Overview
Contacts are the foundation of your billing workflow. Before you can send an invoice, you need someone to send it to. Contacts store customer information like name, email, company, and job title.
Key concepts:
- Each contact belongs to a single organization
- Email addresses must be unique within your organization
- Contacts can be created explicitly via the API, or automatically when you send an invoice to a new email address
- Deleting a contact is a soft delete - the record is retained for historical invoices
tag/Contacts/Creating-a-Contact Creating a Contact
To add a new contact to your address book:
curl -X POST https://api.agree.com/api/v1/contacts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact": {
"name": "Jane Smith",
"email": "jane@acme.com",
"company": "Acme Corporation",
"title": "CFO"
}
}'
Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Jane Smith",
"email": "jane@acme.com",
"company": "Acme Corporation",
"title": "CFO",
"address": null,
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
tag/Contacts/Using-Contacts-with-Invoices Using Contacts with Invoices
Once you have a contact, you can reference them when creating invoices. There are two ways to associate a contact with an invoice:
Option 1: Use contact_id
If you already have a contact, pass their ID:
{
"invoice": {
"contact_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": {"amount": 10000, "currency": "USD"}
}
}
Option 2: Use billing_contact
Pass contact details directly - this will find or create the contact automatically:
{
"invoice": {
"billing_contact": {
"email": "jane@acme.com",
"name": "Jane Smith",
"company": "Acme Corporation"
},
"amount": {"amount": 10000, "currency": "USD"}
}
}
If a contact with that email already exists, their details will be updated. If not, a new contact is created.
tag/Contacts/Listing-and-Filtering-Contacts Listing and Filtering Contacts
Retrieve contacts with optional filtering:
# Get all contacts
curl https://api.agree.com/api/v1/contacts \
-H "Authorization: Bearer YOUR_API_KEY"
# Search by email
curl "https://api.agree.com/api/v1/contacts?email=jane" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by company
curl "https://api.agree.com/api/v1/contacts?company=acme" \
-H "Authorization: Bearer YOUR_API_KEY"
Query Parameters
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
page_size |
integer | Items per page (default: 10, max: 100) |
email |
string | Filter by email address (fuzzy search) |
company |
string | Filter by company name (fuzzy search) |
tag/Contacts/Updating-a-Contact Updating a Contact
Update contact details using PUT:
curl -X PUT https://api.agree.com/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contact": {
"title": "CEO",
"company": "Acme Corp International"
}
}'
tag/Contacts/Deleting-a-Contact Deleting a Contact
Delete a contact by ID:
curl -X DELETE https://api.agree.com/api/v1/contacts/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"
Note: This performs a soft delete. The contact record is retained for historical purposes (existing invoices will still show the contact information), but will no longer appear in your contacts list.
tag/Contacts/Fields-Reference Fields Reference
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique contact identifier |
name |
string | Contact's full name (required) |
email |
string | Contact's email address (required, unique per organization) |
company |
string | Company or organization name |
title |
string | Job title or role |
address |
string | Mailing address |
organization_id |
UUID | Your organization's ID |
inserted_at |
datetime | When the contact was created |
updated_at |
datetime | When the contact was last updated |
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.index List contacts
Returns a paginated list of contacts for the authenticated organization.
Authorizations:
bearer
query Parameters
| page | integer Page number (default: 1) |
| page_size | integer Items per page (default: 10) |
| string Filter by email (fuzzy search) |
|
| company | string Filter by company name (fuzzy search) |
Responses
200
Contacts list
400
Bad Request
401
Unauthorized
get/api/v1/contacts
https://secure.agree.com/api/v1/contacts
Response samples
- 200
- 400
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{"address": "123 Main St, New York, NY 10001",
"company": "Acme Inc",
"email": "john.doe@example.com",
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"name": "John Doe",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"title": "CEO",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"pagination": {"page": 0,
"page_size": 0,
"total_entries": 0,
"total_pages": 0
}
}`
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.create Create contact
Creates a new contact for the authenticated organization.
If a user with the provided email doesn't exist, one will be created automatically. The email must be unique within the organization's contacts.
Authorizations:
bearer
Request Body schema: application/json optional
Contact params
| contact required |
object |
Responses
201
Contact created
401
Unauthorized
422
Validation errors
post/api/v1/contacts
https://secure.agree.com/api/v1/contacts
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"contact": {"company": "Acme Inc",
"email": "john.doe@example.com",
"name": "John Doe",
"title": "CEO"
}
}`
Response samples
- 201
- 401
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"address": "123 Main St, New York, NY 10001",
"company": "Acme Inc",
"email": "john.doe@example.com",
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"name": "John Doe",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"title": "CEO",
"updated_at": "2024-01-15T10:30:00Z"
}
}`
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.delete Delete contact
Deletes a contact by ID.
Authorizations:
bearer
path Parameters
| id required |
string Contact ID (UUID) |
Responses
204
Contact deleted
401
Unauthorized
403
Forbidden
404
Not found
delete/api/v1/contacts/{id}
https://secure.agree.com/api/v1/contacts/{id}
Response samples
- 401
- 403
- 404
Content type
application/json
Copy
`{"error": "Invalid or missing API key"
}`
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.show Get contact
Returns a single contact by ID.
Authorizations:
bearer
path Parameters
| id required |
string Contact ID (UUID) |
Responses
200
Contact
401
Unauthorized
403
Forbidden
404
Not found
get/api/v1/contacts/{id}
https://secure.agree.com/api/v1/contacts/{id}
Response samples
- 200
- 401
- 403
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"address": "123 Main St, New York, NY 10001",
"company": "Acme Inc",
"email": "john.doe@example.com",
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"name": "John Doe",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"title": "CEO",
"updated_at": "2024-01-15T10:30:00Z"
}
}`
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.update (2) Update contact
Updates an existing contact.
Authorizations:
bearer
path Parameters
| id required |
string Contact ID (UUID) |
Request Body schema: application/json optional
Contact params
| contact required |
object |
Responses
200
Contact updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
patch/api/v1/contacts/{id}
https://secure.agree.com/api/v1/contacts/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"contact": {"company": "Acme Inc",
"email": "john.doe@example.com",
"name": "John Doe",
"title": "CEO"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"address": "123 Main St, New York, NY 10001",
"company": "Acme Inc",
"email": "john.doe@example.com",
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"name": "John Doe",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"title": "CEO",
"updated_at": "2024-01-15T10:30:00Z"
}
}`
tag/Contacts/operation/AgreeWeb.API.V1.ContactController.update Update contact
Updates an existing contact.
Authorizations:
bearer
path Parameters
| id required |
string Contact ID (UUID) |
Request Body schema: application/json optional
Contact params
| contact required |
object |
Responses
200
Contact updated
401
Unauthorized
403
Forbidden
404
Not found
422
Validation errors
put/api/v1/contacts/{id}
https://secure.agree.com/api/v1/contacts/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"contact": {"company": "Acme Inc",
"email": "john.doe@example.com",
"name": "John Doe",
"title": "CEO"
}
}`
Response samples
- 200
- 401
- 403
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"address": "123 Main St, New York, NY 10001",
"company": "Acme Inc",
"email": "john.doe@example.com",
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"name": "John Doe",
"organization_id": "660e8400-e29b-41d4-a716-446655440000",
"title": "CEO",
"updated_at": "2024-01-15T10:30:00Z"
}
}`
tag/Webhooks Webhooks
Receive real-time notifications when events occur in your Agree account.
tag/Webhooks/Overview Overview
Webhooks push event data to your application as soon as something happens - like when an invoice is paid or a payment fails. This eliminates the need to poll the API for updates and lets you respond to events instantly.
Key concepts:
- You register a URL endpoint that Agree will call when events occur
- Each endpoint can subscribe to specific event types
- Webhook payloads are signed so you can verify they came from Agree
- Failed deliveries are automatically retried with exponential backoff
tag/Webhooks/Quick-Setup Quick Setup
1. Create an Endpoint
Register a URL to receive webhooks:
Response:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://your-app.com/webhooks/agree",
"events": ["invoice.paid", "invoice.failed"],
"active": true,
"failure_count": 0,
"secret": "whsec_abc123xyz789...",
"inserted_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
Important: Save the secret - it's only returned once at creation. You'll need it to verify webhook signatures.
2. Handle Incoming Webhooks
When an event occurs, Agree sends a POST request to your endpoint:
{
"event": "invoice.paid",
"payload": {
"id": "4a755746-ba45-4226-a669-aebc7ad3719c",
"status": "paid",
"amount": {"amount": 15000, "currency": "USD"},
"paid_at": "2025-01-20T14:30:00Z"
}
}
3. Verify the Signature
Always verify webhooks came from Agree before processing them. See Verifying Webhooks below.
4. Test Your Integration
Send a test webhook to verify your endpoint works:
curl -X POST https://api.agree.com/api/v1/webhook_endpoints/550e8400-e29b-41d4-a716-446655440000/test \
-H "Authorization: Bearer YOUR_API_KEY"
tag/Webhooks/Available-Events Available Events
Subscribe to the events your application needs:
| Event | Description | When it fires |
|---|---|---|
invoice.created |
Invoice was created | After POST /invoices |
invoice.sent |
Invoice emailed to customer | When delivery completes |
invoice.due |
Invoice reached due status | When status becomes due: either the scheduled job runs after sent (past due_at), or the invoice is sent already at/past due_at (immediate due) |
invoice.paid |
Payment successful | After payment confirmation |
invoice.failed |
Payment attempt failed | After payment rejection |
invoice.canceled |
Invoice was canceled | After DELETE /invoices |
invoice.refunded |
Invoice payment was refunded | After refund is processed |
agreement.created |
Agreement was created | After POST /agreements |
agreement.sent |
Agreement was sent to recipients | When status changes to 'sent' |
agreement.signed |
Agreement was signed by a recipient | When a recipient signs |
agreement.executed |
Agreement was fully executed | When all signers have signed |
webhook.test |
Test event | When you trigger a test |
Tip: Start with invoice.paid and invoice.failed - these are the most important for payment integrations.
tag/Webhooks/Webhook-Payload Webhook Payload
Each webhook request includes:
Headers
| Header | Description |
|---|---|
Content-Type |
application/json |
X-Webhook-Signature |
HMAC-SHA256 signature (hex, lowercase) |
X-Webhook-Timestamp |
Unix timestamp when sent |
Body
{
"event": "invoice.paid",
"payload": {
// Full invoice object with all fields
}
}
The payload contains the complete resource object, so you have all the data you need without making additional API calls.
For agreement events (agreement.created, agreement.sent, agreement.signed, agreement.executed), the payload includes the GET /api/v1/agreements/:id response data fields — including flat recipient fields such as recipients[].email and recipients[].name. Webhooks also include nested recipients[].user and recipients[].contact objects for backwards compatibility; prefer the flat fields for new integrations.
tag/Webhooks/Verifying-Webhooks Verifying Webhooks
Always verify webhook signatures before processing. This ensures the request actually came from Agree and wasn't tampered with.
How Verification Works
- Get the raw request body (before JSON parsing)
- Compute HMAC-SHA256 using your endpoint's
secretas the key - Hex-encode the result (lowercase)
- Compare to the
X-Webhook-Signatureheader using constant-time comparison
Node.js Example
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(signatureHeader)
);
}
// Express middleware example
app.post('/webhooks/agree', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!verifyWebhookSignature(req.body, signature, process.env.AGREE_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
switch (event.event) {
case 'invoice.paid':
// Handle successful payment
break;
case 'invoice.failed':
// Handle failed payment
break;
}
res.status(200).send('OK');
});
Python Example
import hmac
import hashlib
from flask import Flask, request
app = Flask(__name__)
def verify_webhook_signature(raw_body, signature_header, secret):
expected_signature = hmac.new(
secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected_signature, signature_header)
@app.route('/webhooks/agree', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Webhook-Signature')
if not verify_webhook_signature(request.data, signature, AGREE_WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.json
if event['event'] == 'invoice.paid':
# Handle successful payment
pass
elif event['event'] == 'invoice.failed':
# Handle failed payment
pass
return 'OK', 200
tag/Webhooks/Managing-Endpoints Managing Endpoints
List All Endpoints
curl https://api.agree.com/api/v1/webhook_endpoints \
-H "Authorization: Bearer YOUR_API_KEY"
Update an Endpoint
Change the subscribed events or URL:
curl -X PUT https://api.agree.com/api/v1/webhook_endpoints/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_endpoint": {
"events": ["invoice.paid", "invoice.failed", "invoice.created"]
}
}'
Disable an Endpoint
Set active to false to temporarily stop receiving webhooks:
curl -X PUT https://api.agree.com/api/v1/webhook_endpoints/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_endpoint": {
"active": false
}
}'
Delete an Endpoint
curl -X DELETE https://api.agree.com/api/v1/webhook_endpoints/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_API_KEY"
tag/Webhooks/Retry-Policy Retry Policy
If your endpoint returns a non-2xx status code or times out, Agree automatically retries:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | ~1 minute |
| 3 | ~5 minutes |
| 4 | ~30 minutes |
| 5 | ~2 hours |
After 5 failed attempts, the webhook is marked as failed and the endpoint's failure_count is incremented.
Tip: Monitor failure_count to detect integration issues. If it keeps increasing, check your endpoint's logs.
tag/Webhooks/Best-Practices Best Practices
- Respond quickly - Return 200 within 5 seconds, then process asynchronously
- Handle duplicates - Webhooks may occasionally be sent more than once; use idempotency
- Verify signatures - Never skip verification in production
- Use HTTPS - Required in production for security
- Log everything - Store webhook payloads for debugging and auditing
tag/Webhooks/Fields-Reference Fields Reference
| Field | Type | Description |
|---|---|---|
id |
UUID | Unique endpoint identifier |
url |
string | Your webhook URL (HTTPS required in production) |
events |
array | Event types this endpoint receives |
active |
boolean | Whether the endpoint is receiving webhooks |
failure_count |
integer | Consecutive failed deliveries |
secret |
string | Signing secret (only returned on creation) |
inserted_at |
datetime | When the endpoint was created |
updated_at |
datetime | When the endpoint was last modified |
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.index List webhook endpoints
Returns all webhook endpoints for the authenticated organization.
Authorizations:
bearer
Responses
200
Webhook endpoints list
401
Unauthorized
get/api/v1/webhooks
https://secure.agree.com/api/v1/webhooks
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{"active": true,
"events": ["invoice.created",
"invoice.paid"
],
"failure_count": 0,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"url": "https://example.com/webhooks"\
}
]
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.create Create webhook endpoint
Creates a new webhook endpoint for the authenticated organization.
Important: The signing secret is only returned once in the response when the endpoint is created.
Store it securely as it cannot be retrieved again.
Use the secret to verify webhook signatures by computing an HMAC-SHA256 of the request body
and comparing it to the X-Agree-Signature header.
Authorizations:
bearer
Request Body schema: application/json optional
Webhook endpoint params
| webhook_endpoint required |
object |
Responses
201
Webhook endpoint created
401
Unauthorized
422
Validation errors
post/api/v1/webhooks
https://secure.agree.com/api/v1/webhooks
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"webhook_endpoint": {"events": ["invoice.created",
"invoice.paid",
"invoice.failed"
],
"url": "https://example.com/webhooks"
}
}`
Response samples
- 201
- 401
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"active": true,
"events": ["string"
],
"failure_count": 0,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"inserted_at": "2019-08-24T14:15:22Z",
"secret": "string",
"updated_at": "2019-08-24T14:15:22Z",
"url": "http://example.com"
}
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.delete Delete webhook endpoint
Deletes a webhook endpoint by ID.
Authorizations:
bearer
path Parameters
| id required |
string Webhook endpoint ID (UUID) |
Responses
204
Webhook endpoint deleted
401
Unauthorized
404
Not found
delete/api/v1/webhooks/{id}
https://secure.agree.com/api/v1/webhooks/{id}
Response samples
- 401
- 404
Content type
application/json
Copy
`{"error": "Invalid or missing API key"
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.show Get webhook endpoint
Returns a single webhook endpoint by ID.
Authorizations:
bearer
path Parameters
| id required |
string Webhook endpoint ID (UUID) |
Responses
200
Webhook endpoint
401
Unauthorized
404
Not found
get/api/v1/webhooks/{id}
https://secure.agree.com/api/v1/webhooks/{id}
Response samples
- 200
- 401
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"active": true,
"events": ["invoice.created",
"invoice.paid"
],
"failure_count": 0,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"url": "https://example.com/webhooks"
}
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.update (2) Update webhook endpoint
Updates an existing webhook endpoint.
Authorizations:
bearer
path Parameters
| id required |
string Webhook endpoint ID (UUID) |
Request Body schema: application/json optional
Webhook endpoint params
| webhook_endpoint required |
object |
Responses
200
Webhook endpoint updated
401
Unauthorized
404
Not found
422
Validation errors
patch/api/v1/webhooks/{id}
https://secure.agree.com/api/v1/webhooks/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"webhook_endpoint": {"events": ["invoice.created",
"invoice.paid",
"invoice.failed"
],
"url": "https://example.com/webhooks"
}
}`
Response samples
- 200
- 401
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"active": true,
"events": ["invoice.created",
"invoice.paid"
],
"failure_count": 0,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"url": "https://example.com/webhooks"
}
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.update Update webhook endpoint
Updates an existing webhook endpoint.
Authorizations:
bearer
path Parameters
| id required |
string Webhook endpoint ID (UUID) |
Request Body schema: application/json optional
Webhook endpoint params
| webhook_endpoint required |
object |
Responses
200
Webhook endpoint updated
401
Unauthorized
404
Not found
422
Validation errors
put/api/v1/webhooks/{id}
https://secure.agree.com/api/v1/webhooks/{id}
Request samples
- Payload
Content type
application/json
Copy Expand all Collapse all
`{"webhook_endpoint": {"events": ["invoice.created",
"invoice.paid",
"invoice.failed"
],
"url": "https://example.com/webhooks"
}
}`
Response samples
- 200
- 401
- 404
- 422
Content type
application/json
Copy Expand all Collapse all
`{"data": {"active": true,
"events": ["invoice.created",
"invoice.paid"
],
"failure_count": 0,
"id": "550e8400-e29b-41d4-a716-446655440000",
"inserted_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"url": "https://example.com/webhooks"
}
}`
tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.test Send test webhook
Sends a test webhook payload to all endpoints subscribed to the webhook.test event.
This is useful for verifying your webhook endpoint is properly configured to receive events.
The test payload contains:
{
"test": true,
"message": "This is a test webhook from Agree",
"timestamp": "2024-01-15T10:30:00Z"
}
Authorizations:
bearer
Responses
202
Test webhooks queued
401
Unauthorized
404
No endpoints subscribed to webhook.test
post/api/v1/webhooks/test
https://secure.agree.com/api/v1/webhooks/test
Response samples
- 202
- 401
- 404
Content type
application/json
Copy Expand all Collapse all
`{"data": {"failed": 0,
"job_ids": [123,
124
],
"message": "Test webhooks have been queued and will be sent shortly",
"successful": 2,
"total": 2
}
}`
tag/Reports Reports
Read-only analytics for revenue, cashflow, and accounts receivable recovery.
tag/Reports/Overview Overview
Report endpoints mirror the in-app Reports dashboards (/reports/revenue, /reports/cashflow, /reports/recovery). All metrics are scoped to the authenticated API key's organization.
Amounts use the Money object shape: amount is in the smallest currency unit (cents for USD) and currency is an ISO 4217 code (e.g. "USD").
tag/Reports/Revenue Revenue
| Endpoint | Description |
|---|---|
GET /reports/revenue/stats |
ARR, MRR, growth, NRR, top-5 concentration |
GET /reports/revenue/chart |
Monthly MRR/ARR history and forecast |
GET /reports/revenue/customers |
Customers ranked by paid revenue |
GET /reports/revenue/customers_by_mrr |
Customers ranked by subscription MRR |
tag/Reports/Cashflow Cashflow
| Endpoint | Description |
|---|---|
GET /reports/cashflow/stats |
Cash collected MTD, outstanding total, DSO, fail rate |
GET /reports/cashflow/chart |
Monthly cash collected history and forecast |
GET /reports/cashflow/outstanding_invoices |
Outstanding invoice list |
GET /reports/cashflow/forecast |
Expected cash in next 30/60/90 days |
tag/Reports/Recovery Recovery
| Endpoint | Description |
|---|---|
GET /reports/recovery/aging/chart |
Aging buckets by month |
GET /reports/recovery/aging/invoices |
Invoices grouped by aging bucket |
GET /reports/recovery/aging/trend |
Overdue totals and average days overdue |
GET /reports/recovery/leakage/stats |
Counts/amounts by invoice stage |
GET /reports/recovery/leakage/waterfall |
Stage waterfall for leakage analysis |
GET /reports/recovery/leakage/stalled_invoices |
Stalled invoices |
GET /reports/recovery/leakage/stage_durations |
Average days between stages |
tag/Reports/operation/AgreeWeb.API.V1.ReportController.revenue_stats Revenue statistics
Returns ARR, MRR, MRR growth rate, net revenue retention (NRR), and top-5 customer concentration.
Authorizations:
bearer
Responses
200
Revenue statistics
401
Unauthorized
get/api/v1/reports/revenue/stats
https://secure.agree.com/api/v1/reports/revenue/stats
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_aging_trend Aging trend
Returns total overdue amount and average days overdue per month.
Authorizations:
bearer
Responses
200
Aging trend
401
Unauthorized
get/api/v1/reports/recovery/aging/trend
https://secure.agree.com/api/v1/reports/recovery/aging/trend
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.revenue_chart Revenue chart data
Returns historical and forecast MRR/ARR by month.
Authorizations:
bearer
Responses
200
Revenue chart
401
Unauthorized
get/api/v1/reports/revenue/chart
https://secure.agree.com/api/v1/reports/revenue/chart
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_leakage_stage_durations Stage duration statistics
Returns average days between invoice stages for current vs previous six-month periods.
Authorizations:
bearer
Responses
200
Stage durations
401
Unauthorized
get/api/v1/reports/recovery/leakage/stage_durations
https://secure.agree.com/api/v1/reports/recovery/leakage/stage\_durations
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_leakage_stats Leakage statistics
Returns invoice counts and amounts by stage (drafted, outstanding, overdue, paid).
Authorizations:
bearer
Responses
200
Leakage statistics
401
Unauthorized
get/api/v1/reports/recovery/leakage/stats
https://secure.agree.com/api/v1/reports/recovery/leakage/stats
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_leakage_waterfall Leakage waterfall
Returns waterfall stages for invoice progression (drafted → outstanding → overdue → paid).
Authorizations:
bearer
Responses
200
Leakage waterfall
401
Unauthorized
get/api/v1/reports/recovery/leakage/waterfall
https://secure.agree.com/api/v1/reports/recovery/leakage/waterfall
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.cashflow_chart Cashflow chart data
Returns historical and forecast cash collected by month.
Authorizations:
bearer
Responses
200
Cashflow chart
401
Unauthorized
get/api/v1/reports/cashflow/chart
https://secure.agree.com/api/v1/reports/cashflow/chart
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_leakage_stalled_invoices Stalled invoices
Lists invoices that have been stalled in a workflow stage.
Authorizations:
bearer
Responses
200
Stalled invoices
401
Unauthorized
get/api/v1/reports/recovery/leakage/stalled_invoices
https://secure.agree.com/api/v1/reports/recovery/leakage/stalled\_invoices
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.cashflow_forecast Cash forecast
Returns projected cash from outstanding invoices due in the next 30, 60, and 90 days.
Authorizations:
bearer
Responses
200
Cash forecast
401
Unauthorized
get/api/v1/reports/cashflow/forecast
https://secure.agree.com/api/v1/reports/cashflow/forecast
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.revenue_customers_by_mrr Customers by MRR
Lists customers ranked by current monthly recurring revenue from active subscriptions.
Authorizations:
bearer
Responses
200
Customers by MRR
401
Unauthorized
get/api/v1/reports/revenue/customers_by_mrr
https://secure.agree.com/api/v1/reports/revenue/customers\_by\_mrr
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.cashflow_outstanding_invoices Outstanding invoices
Lists outstanding (sent or due) invoices with customer and aging details.
Authorizations:
bearer
Responses
200
Outstanding invoices
401
Unauthorized
get/api/v1/reports/cashflow/outstanding_invoices
https://secure.agree.com/api/v1/reports/cashflow/outstanding\_invoices
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.cashflow_stats Cashflow statistics
Returns cash collected month-to-date, outstanding invoice total, days sales outstanding (DSO), and payment failure rate.
Authorizations:
bearer
Responses
200
Cashflow statistics
401
Unauthorized
get/api/v1/reports/cashflow/stats
https://secure.agree.com/api/v1/reports/cashflow/stats
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.revenue_customers Customers by revenue
Lists customers ranked by total paid invoice revenue.
Authorizations:
bearer
Responses
200
Customers by revenue
401
Unauthorized
get/api/v1/reports/revenue/customers
https://secure.agree.com/api/v1/reports/revenue/customers
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_aging_chart Aging chart data
Returns overdue invoice amounts by aging bucket for the past six months.
Authorizations:
bearer
Responses
200
Aging chart
401
Unauthorized
get/api/v1/reports/recovery/aging/chart
https://secure.agree.com/api/v1/reports/recovery/aging/chart
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": [{ }
]
}`
tag/Reports/operation/AgreeWeb.API.V1.ReportController.recovery_aging_invoices Invoices by aging bucket
Lists outstanding invoices grouped by aging bucket (current, 1-30, 31-60, 61-90, 90+ days).
Authorizations:
bearer
Responses
200
Invoices by aging
401
Unauthorized
get/api/v1/reports/recovery/aging/invoices
https://secure.agree.com/api/v1/reports/recovery/aging/invoices
Response samples
- 200
- 401
Content type
application/json
Copy Expand all Collapse all
`{"data": { }
}`