- 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](https://secure.agree.com/documentation/openapi)

## [section/Introduction](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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:

```bash
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:

```bash
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:

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#section/Introduction/Base-URL) Base URL

All API requests should be made to:

```
https://api.agree.com/api/v1
```

## [section/Introduction/Authentication](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#section/Introduction/Request-Format) Request Format

Send request bodies as JSON with the `Content-Type: application/json` header.

## [section/Introduction/Response-Format](https://secure.agree.com/documentation\#section/Introduction/Response-Format) Response Format

All successful responses return JSON with a `data` wrapper:

```json
{
  "data": { ... }
}
```

List endpoints include pagination information:

```json
{
  "data": [ ... ],
  "pagination": {
    "page": 1,
    "page_size": 10,
    "total_pages": 5,
    "total_entries": 42
  }
}
```

## [section/Introduction/Errors](https://secure.agree.com/documentation\#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:

```json
{
  "errors": {
    "email": ["has already been taken"],
    "amount": ["must be greater than 0"]
  }
}
```

## [section/Introduction/Pagination](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#section/Introduction/Need-Help) Need Help?

- Check the endpoint documentation below for detailed parameter information
- Test webhooks using the `webhook.test` event
- Contact [support@agree.com](mailto:support@agree.com) for API assistance

## [tag/Agreements](https://secure.agree.com/documentation\#tag/Agreements) Agreements

Create, send, and manage agreements with recipients and field assignments.

## [tag/Agreements/Overview](https://secure.agree.com/documentation\#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 `owner` role (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_id` or by providing contact details inline

## [tag/Agreements/Creating-an-Agreement](https://secure.agree.com/documentation\#tag/Agreements/Creating-an-Agreement) Creating an Agreement

### Basic Agreement Creation

Here's a basic example of creating an agreement from a template:

```bash
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:**

```json
{
  "recipients": [\
    {\
      "contact_id": "YOUR_CONTACT_ID",\
      "role": "owner"\
    },\
    {\
      "contact_id": "CLIENT_CONTACT_ID",\
      "role": "signer"\
    }\
  ]
}
```

**Incorrect approach (will fail):**

```json
{
  "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:

```bash
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:

```bash
curl "https://api.agree.com/api/v1/contacts?email=your-email@example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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**

```bash
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_address` and `date` fields
- The signer is assigned `signature_field` and `date_field` fields

**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:**

```bash
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](https://secure.agree.com/documentation\#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:

```bash
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**

```bash
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:**

```json
{
  "data": {
    "id": "990e8400-e29b-41d4-a716-446655440000",
    ...
  }
}
```

**Step 2: Create Invoice and Link to Agreement**

```bash
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](https://secure.agree.com/documentation\#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)](https://secure.agree.com/documentation\#tag/Agreements/Field-Values-(Prefilling)) Field Values (Prefilling)

You can prefill field values when creating an agreement:

```json
{
  "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`):

```bash
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:

1. **A string** (legacy): plain text. Works for any field or variable.
2. **An object** with a `content` string and optional `content_type`:

```json
{
     "content": "<strong>Renewal</strong> 2026-05-01",
     "content_type": "html"
}
```

- `content` (required): the payload.
   - `content_type` (optional): `plaintext`, `html`, or `markdown`. If omitted, **`plaintext`** is used.

**Rich text applies only to template variables.** If the `field_values` key matches a **variable**`field_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)](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation#typed-values-and-rich-text).

### Step 1: Discover Template Variables

Fetch the template to see its variables:

```bash
curl https://api.agree.com/api/v1/agreements/templates/TEMPLATE_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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.

```bash
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):

```json
"var_abc123": "Jane Smith"
```

HTML (lists, emphasis, etc.):

```json
"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_`):

```json
"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:

```json
"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`:

```json
{
  "error": "Unfilled variables: Employee Name, Start Date. All variables must have values before sending."
}
```

## [tag/Agreements/Listing-Agreements](https://secure.agree.com/documentation\#tag/Agreements/Listing-Agreements) Listing Agreements

Retrieve agreements with optional filtering:

```bash
# 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](https://secure.agree.com/documentation\#tag/Agreements/Sending-an-Agreement) Sending an Agreement

After creating an agreement, send it to recipients:

```bash
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 automatically
- `embedded` \- Emails are suppressed (you handle delivery yourself)

## [tag/Agreements/Create-and-Send-in-One-Step](https://secure.agree.com/documentation\#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:

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation#typed-values-and-rich-text).

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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<br>required | string<br>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](https://secure.agree.com/documentation\#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<br>required | string<br>Agreement ID (UUID) |

##### Request Body schema: application/json  optional

Send params

|     |     |
| --- | --- |
| delivery\_method | string<br>Value:"email"<br>Delivery method (only valid for managed mode) |
| delivery\_mode<br>required | string<br>Enum:"embedded""managed"<br>Delivery mode: 'embedded' (emails suppressed) or 'managed' (Agree sends emails) |
| message | string or null<br>Optional message to include in email (only valid for managed mode) |
| reminder\_schedule | string or null<br>Enum:"none""daily""weekly""monthly"<br>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](https://secure.agree.com/documentation\#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<br>Enum:"embedded""managed"<br>Delivery mode: 'embedded' (emails suppressed) or 'managed' (Agree sends emails) |
| ends\_at | string or null <date-time> <br>When the agreement ends (ISO8601 format) |
| field\_values | object<br>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<br>Invoice to create with this agreement. Creates an invoice template associated with the agreement.<br>Either `billing_contact` or `contact_id` is required when providing an invoice.<br>Either `amount`/`currency` or `line_items` is required (if line\_items are provided, amount is calculated from them).<br>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<br>required | string<br>Agreement name |
| payments\_enabled | boolean<br>Whether payments are enabled for this agreement |
| recipients | Array of objects<br>List of recipients with their assigned fields.<br>**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.<br>Each recipient must provide either `contact_id` or `contact` (but not both).<br>- `contact_id`: Reference an existing contact<br>- `contact`: Create or update a contact with email and name (required), and optionally company and title<br>Use `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<br>Enum:"none""daily""weekly""monthly"<br>Reminder schedule frequency (only valid for managed mode) |
| signing\_order | Array of strings <uuid> \[ items <uuid > \]<br>List of contact IDs in signing order |
| signing\_order\_enabled | boolean<br>Whether signing order is enabled |
| starts\_at | string or null <date-time> <br>When the agreement starts (ISO8601 format) |
| template\_id<br>required | string <uuid> <br>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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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<br>Page number (default: 1) |
| page\_size | integer<br>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](https://secure.agree.com/documentation\#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_id` to reference an existing contact
- `contact` with `email` and `name` (and optionally `company` and `title`) 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](https://secure.agree.com/documentation\#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<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.delete) Delete agreement

Deletes an agreement by ID (soft delete).

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.show) Get agreement

Returns a single agreement by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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)](https://secure.agree.com/documentation\#tag/Agreements/operation/AgreeWeb.API.V1.AgreementController.update%20(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<br>required | string<br>Agreement ID (UUID) |

##### Request Body schema: application/json  optional

Agreement params

|     |     |
| --- | --- |
| agreement<br>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](https://secure.agree.com/documentation\#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<br>required | string<br>Agreement ID (UUID) |

##### Request Body schema: application/json  optional

Agreement params

|     |     |
| --- | --- |
| agreement<br>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](https://secure.agree.com/documentation\#tag/Invoices) Invoices

Create, send, and track payment requests to your customers.

## [tag/Invoices/Overview](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#tag/Invoices/Common-Use-Cases) Common Use Cases

### Bill a Client for a Completed Project

Send a one-time invoice after completing work:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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](https://secure.agree.com/documentation\#tag/Invoices/Creating-an-Invoice) Creating an Invoice

Here's a basic invoice creation:

```bash
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:**

```json
{
  "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:

```bash
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`:

```bash
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:**

```json
{
  "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` |

```json
{
  "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):

```json
{
  "invoice": {
    "billing_contact": {
      "email": "customer@example.com",
      "name": "John Doe"
    }
  }
}
```

This creates or updates a contact automatically.

**Using `contact_id`** (for existing contacts):

```json
{
  "invoice": {
    "contact_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

You cannot use both in the same request.

## [tag/Invoices/Invoice-Lifecycle](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#tag/Invoices/Recurring-Invoices) Recurring Invoices

Set up automatic recurring invoices by providing `recurring_options`:

```bash
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:**

```json
{
  "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:**

```json
{
  "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](https://secure.agree.com/documentation\#tag/Invoices/Listing-and-Filtering-Invoices) Listing and Filtering Invoices

Retrieve invoices with powerful filtering options:

```bash
# 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](https://secure.agree.com/documentation\#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:

```bash
curl -X POST https://api.agree.com/api/v1/invoices/4a755746-ba45-4226-a669-aebc7ad3719c/send \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json
{
  "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](https://secure.agree.com/documentation\#tag/Invoices/Updating-an-Invoice) Updating an Invoice

Update invoice details before payment:

```bash
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](https://secure.agree.com/documentation\#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

```bash
curl "https://api.agree.com/api/v1/invoices/INVOICE_ID/pdf" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response (200):**

```json
{
  "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**.

```bash
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](https://secure.agree.com/documentation\#tag/Invoices/Canceling-an-Invoice) Canceling an Invoice

Cancel an unpaid invoice:

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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<br>required | string<br>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](https://secure.agree.com/documentation\#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<br>required | string<br>Invoice ID (UUID) |

##### Request Body schema: application/json  optional

Mark as sent params

|     |     |
| --- | --- |
| sent\_at | string <date> <br>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](https://secure.agree.com/documentation\#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<br>required | string<br>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](https://secure.agree.com/documentation\#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<br>Page number (default: 1) |
| page\_size | integer<br>Items per page (default: 10) |
| date\_start | string<br>Start date for filtering (ISO8601 format: YYYY-MM-DD) |
| date\_end | string<br>End date for filtering (ISO8601 format: YYYY-MM-DD) |
| date\_type | string<br>Date field to filter by. Valid values: paid\_at, due\_at, scheduled\_at (default: scheduled\_at) |
| date\_timezone | string<br>Timezone for date filtering (default: Etc/UTC) |
| statuses | string<br>Filter by invoice statuses (comma-separated). Valid values: created, due, sent, canceled, paid, failed, refunded, draft |
| amount\_min | number<br>Minimum invoice amount (in dollars) |
| amount\_max | number<br>Maximum invoice amount (in dollars) |
| customer | string<br>Filter by customer/company name (fuzzy search) |
| include\_drafts | boolean<br>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](https://secure.agree.com/documentation\#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_options` to configure recurring settings. If not provided, the invoice will have no recurring schedule (schedule: "none").

You can optionally provide either:

- `billing_contact` with `email` and `name` (and optionally `company` and `title`) to automatically create or update a contact
- `contact_id` to 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<br>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](https://secure.agree.com/documentation\#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<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.delete) Delete invoice

Deletes an invoice by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.show) Get invoice

Returns a single invoice by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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)](https://secure.agree.com/documentation\#tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.update%20(2)) Update invoice

Updates an existing invoice.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Invoice ID (UUID) |

##### Request Body schema: application/json  optional

Invoice params

|     |     |
| --- | --- |
| invoice<br>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](https://secure.agree.com/documentation\#tag/Invoices/operation/AgreeWeb.API.V1.InvoiceController.update) Update invoice

Updates an existing invoice.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Invoice ID (UUID) |

##### Request Body schema: application/json  optional

Invoice params

|     |     |
| --- | --- |
| invoice<br>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](https://secure.agree.com/documentation\#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<br>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](https://secure.agree.com/documentation\#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<br>required | string<br>Invoice ID (UUID) |

##### Request Body schema: application/json  optional

Mark as paid params

|     |     |
| --- | --- |
| paid\_at | string <date> <br>Date when invoice was paid (ISO8601 format: YYYY-MM-DD). Defaults to today. |
| payment\_method | string<br>Enum:"manual""ach""card""wire"<br>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](https://secure.agree.com/documentation\#tag/Contacts) Contacts

Manage your organization's contacts - the people and companies you do business with.

## [tag/Contacts/Overview](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#tag/Contacts/Creating-a-Contact) Creating a Contact

To add a new contact to your address book:

```bash
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:**

```json
{
  "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](https://secure.agree.com/documentation\#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:

```json
{
  "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:

```json
{
  "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](https://secure.agree.com/documentation\#tag/Contacts/Listing-and-Filtering-Contacts) Listing and Filtering Contacts

Retrieve contacts with optional filtering:

```bash
# 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](https://secure.agree.com/documentation\#tag/Contacts/Updating-a-Contact) Updating a Contact

Update contact details using PUT:

```bash
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](https://secure.agree.com/documentation\#tag/Contacts/Deleting-a-Contact) Deleting a Contact

Delete a contact by ID:

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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<br>Page number (default: 1) |
| page\_size | integer<br>Items per page (default: 10) |
| email | string<br>Filter by email (fuzzy search) |
| company | string<br>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](https://secure.agree.com/documentation\#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<br>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](https://secure.agree.com/documentation\#tag/Contacts/operation/AgreeWeb.API.V1.ContactController.delete) Delete contact

Deletes a contact by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Contacts/operation/AgreeWeb.API.V1.ContactController.show) Get contact

Returns a single contact by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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)](https://secure.agree.com/documentation\#tag/Contacts/operation/AgreeWeb.API.V1.ContactController.update%20(2)) Update contact

Updates an existing contact.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Contact ID (UUID) |

##### Request Body schema: application/json  optional

Contact params

|     |     |
| --- | --- |
| contact<br>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](https://secure.agree.com/documentation\#tag/Contacts/operation/AgreeWeb.API.V1.ContactController.update) Update contact

Updates an existing contact.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Contact ID (UUID) |

##### Request Body schema: application/json  optional

Contact params

|     |     |
| --- | --- |
| contact<br>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](https://secure.agree.com/documentation\#tag/Webhooks) Webhooks

Receive real-time notifications when events occur in your Agree account.

## [tag/Webhooks/Overview](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#tag/Webhooks/Quick-Setup) Quick Setup

### 1\. Create an Endpoint

Register a URL to receive webhooks:

**Response:**

```json
{
  "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:

```json
{
  "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](https://secure.agree.com/documentation#verifying-webhooks) below.

### 4\. Test Your Integration

Send a test webhook to verify your endpoint works:

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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

```json
{
  "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](https://secure.agree.com/documentation\#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

1. Get the raw request body (before JSON parsing)
2. Compute HMAC-SHA256 using your endpoint's `secret` as the key
3. Hex-encode the result (lowercase)
4. Compare to the `X-Webhook-Signature` header using constant-time comparison

### Node.js Example

```javascript
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

```python
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](https://secure.agree.com/documentation\#tag/Webhooks/Managing-Endpoints) Managing Endpoints

### List All Endpoints

```bash
curl https://api.agree.com/api/v1/webhook_endpoints \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Update an Endpoint

Change the subscribed events or URL:

```bash
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:

```bash
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

```bash
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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#tag/Webhooks/Best-Practices) Best Practices

1. **Respond quickly** \- Return 200 within 5 seconds, then process asynchronously
2. **Handle duplicates** \- Webhooks may occasionally be sent more than once; use idempotency
3. **Verify signatures** \- Never skip verification in production
4. **Use HTTPS** \- Required in production for security
5. **Log everything** \- Store webhook payloads for debugging and auditing

## [tag/Webhooks/Fields-Reference](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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<br>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](https://secure.agree.com/documentation\#tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.delete) Delete webhook endpoint

Deletes a webhook endpoint by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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](https://secure.agree.com/documentation\#tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.show) Get webhook endpoint

Returns a single webhook endpoint by ID.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>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)](https://secure.agree.com/documentation\#tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.update%20(2)) Update webhook endpoint

Updates an existing webhook endpoint.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Webhook endpoint ID (UUID) |

##### Request Body schema: application/json  optional

Webhook endpoint params

|     |     |
| --- | --- |
| webhook\_endpoint<br>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](https://secure.agree.com/documentation\#tag/Webhooks/operation/AgreeWeb.API.V1.WebhookEndpointController.update) Update webhook endpoint

Updates an existing webhook endpoint.

##### Authorizations:

_bearer_

##### path Parameters

|     |     |
| --- | --- |
| id<br>required | string<br>Webhook endpoint ID (UUID) |

##### Request Body schema: application/json  optional

Webhook endpoint params

|     |     |
| --- | --- |
| webhook\_endpoint<br>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](https://secure.agree.com/documentation\#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:

```json
{
  "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](https://secure.agree.com/documentation\#tag/Reports) Reports

Read-only analytics for revenue, cashflow, and accounts receivable recovery.

## [tag/Reports/Overview](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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](https://secure.agree.com/documentation\#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": { }

}`
