Skip to content

/sales/invoices

Path: /sales/invoices
Namespace: sales
Resource: invoices

Overview

Sales invoices use the same JSON resource shape and relationships as Admin Invoices. For GET /sales/invoices.json, the server only returns invoices that match the sales view of the tenant (current domain, seller/supplier parties, and the seller agent tied to the signed-in user). If an invoice you expect is missing from this list, compare seller_id, supplier_id, and seller_agent_id on the record against your session context, or open it under /admin/invoices if your app has access.

Relationships

See Admin Invoices for fields and associations. Use the routes in this page for all sales JSON calls.

Seller, supplier, and seller agent (API behavior)

  • GET /sales/invoices.json: Results are already filtered for the sales workspace; optional Ransack params such as q[seller_id_eq]= must still be consistent with that view or the row will not appear.
  • POST /sales/invoices.json: You can send seller_id (and other allowed invoice fields) in the JSON body when creating or updating an unconfirmed invoice; omit seller_id only if your integration relies on server-side defaults for the current host.
  • Example: Minimal create:
    javascript
    const invoice = await fetch('/sales/invoices.json', {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify({
        invoice: {
          invoice_type: 'invoice',
          buyer_id: 2,
          date: '2026-03-15'
        }
      })
    }).then(r => r.json());

Supplier

Supplier party fields behave like admin; see Admin Invoices.

Key Features

  • Filtered index: GET /sales/invoices.json returns the sales-oriented subset for the current session.
  • Same JSON resource as admin for show/create/update/delete where your credentials allow.
  • Nested lines: Use POST /sales/invoices/:id/invoice_lines.json (and related line routes), not a nested payload on the invoice create, unless your deployment documents otherwise.

Available Operations

List Invoices (GET)

Endpoint: GET /sales/invoices.json

Query Parameters:

  • q[field_predicate]=value - Ransack query filters for advanced filtering
  • scope=name - Apply a named list scope (e.g. active, unpaid, due, leads, orders; see Scopes below)
  • page=N - Page number for pagination
  • per_page=N - Items per page (default: 25)

Request Examples:

bash
curl -X GET "https://your-company.erpax.com/sales/invoices.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"
bash
curl -X GET "https://your-company.erpax.com/sales/invoices.json?scope=unpaid" \
  -H "Accept: application/json"

JavaScript Example:

javascript
const response = await fetch('/sales/invoices.json', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
});
const data = await response.json();

Response (200 OK):

json
{
  "invoices": [
    {
      "id": 1,
      "invoice_type": "invoice",
      "number": "INV-2026-001",
      "date": "2026-03-15",
      "seller_id": 1,
      "buyer_id": 2,
      "total_amount_cents": 100000,
      "confirmed": true
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total_pages": 5,
    "total_count": 123
  }
}

Show Invoice (GET /:id)

Endpoint: GET /sales/invoices/:id.json

Request Example:

bash
curl -X GET "https://your-company.erpax.com/sales/invoices/123.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "invoice_type": "invoice",
    "number": "INV-2026-001",
    "date": "2026-03-15",
    "seller_id": 1,
    "buyer_id": 2,
    "total_amount_cents": 100000,
    "confirmed": true
  }
}

Create Invoice (POST)

Endpoint: POST /sales/invoices.json

Request Example:

bash
curl -X POST "https://your-company.erpax.com/sales/invoices.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "invoice": {
      "invoice_type": "invoice",
      "buyer_id": 2,
      "date": "2026-03-15",
      "currency_code": "USD"
    }
  }'

Notes

  • seller_id: Include when you need a specific seller address on the created invoice so it appears under GET /sales/invoices.json for your sales session.
  • Line items: Use POST /sales/invoices/:invoice_id/invoice_lines.json (see Sales invoice lines). Do not rely on embedding lines in the invoice create body unless your server accepts that shape.

JavaScript Example:

javascript
const response = await fetch('/sales/invoices.json', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    invoice: {
      invoice_type: 'invoice',
      buyer_id: 2,
      date: '2026-03-15',
      currency_code: 'USD'
    }
  })
});
const invoice = await response.json();

Response (201 Created):

json
{
  "invoice": {
    "id": 123,
    "invoice_type": "invoice",
    "seller_id": 1,
    "buyer_id": 2,
    "date": "2026-03-15",
    "currency_code": "USD",
    "total_amount_cents": 100000,
    "confirmed": false,
    "created_at": "2026-03-15T14:30:00Z"
  }
}

Update Invoice (PATCH /:id)

Endpoint: PATCH /sales/invoices/:id.json

Request Example:

bash
curl -X PATCH "https://your-company.erpax.com/sales/invoices/123.json" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie" \
  -d '{
    "invoice": {
      "confirmed": true
    }
  }'

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "confirmed": true,
    "updated_at": "2026-03-15T15:00:00Z"
  }
}

Delete Invoice (DELETE /:id)

Endpoint: DELETE /sales/invoices/:id.json

Request Example:

bash
curl -X DELETE "https://your-company.erpax.com/sales/invoices/123.json" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (204 No Content):

(empty response)

Member Actions

Custom actions available on individual invoices via API:

Renew Invoice

Endpoint: POST /sales/invoices/:id/renew

Description: Renew a recurring invoice (subscription or lease).

Request Example:

bash
curl -X POST "https://your-company.erpax.com/sales/invoices/123/renew" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "invoice": {
    "id": 123,
    "next_billing_date": "2026-04-15",
    "updated_at": "2026-03-15T15:00:00Z"
  }
}

Email Invoice

Endpoint: GET /sales/invoices/:id/email

Description: Send the invoice via email to the buyer.

Request Example:

bash
curl -X GET "https://your-company.erpax.com/sales/invoices/123/email" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (200 OK):

json
{
  "message": "Email sent successfully"
}

Endpoint: GET /sales/invoices/:id/print

Description: Generate and return a printable version of the invoice.

Request Example:

bash
curl -X GET "https://your-company.erpax.com/sales/invoices/123/print" \
  -H "Accept: application/pdf" \
  -H "Cookie: session_cookie"

Response: Returns PDF or HTML printable version of the invoice.

Duplicate Invoice

Endpoint: POST /sales/invoices/:id/duplicate

Description: Create a duplicate copy of the invoice.

Request Example:

bash
curl -X POST "https://your-company.erpax.com/sales/invoices/123/duplicate" \
  -H "Accept: application/json" \
  -H "Cookie: session_cookie"

Response (201 Created):

json
{
  "invoice": {
    "id": 124,
    "invoice_type": "invoice",
    "number": null,
    "date": "2026-03-15",
    "created_at": "2026-03-15T15:00:00Z"
  }
}

Scopes

Pass a scope as a query parameter, for example GET /sales/invoices.json?scope=unpaid.

Available scope values on this route include active (default), pending, renewable, leads, orders, invoices, credits, paid, unpaid, and due. Admin Invoices documents additional scopes (accounting, aging, cancelled, etc.) available only under /admin/invoices.

Filters

Use Ransack-style query params q[...] on GET /sales/invoices.json the same way as on GET /admin/invoices.json (numbers, parties, dates, amounts, etc.). Which PATCH / POST attributes succeed depends on your session; treat 422 / 403 responses as the source of truth for allowed fields.

Business Rules

  • GET /sales/invoices.json returns only invoices visible in the sales workspace for the current user and domain.
  • Writes (POST, PATCH, DELETE) follow the same rules as other namespaces for confirmed documents and payments; unauthorized actions return an error response.
  • For full capability and extra scopes, use Admin Invoices routes where your app has access.

Released under an open source license.