CanopyDocs
Reference

Billing

GET
/api/billing/invoices

Newest first. Unpaginated unless page is sent, in which case limit (default 25, max 250) applies and pagination is returned beside data; without page, limit is ignored and every invoice in scope is returned. A client-pinned credential sees only its own client's invoices; clientId and X-Client-Id are ignored for it.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Query Parameters

page?integer
Range0 < value
limit?integer
Range0 < value <= 250
search?string
Lengthlength <= 200
sent?string

Value in

  • "ALL"
  • "SENT"
  • "UNSENT"
clientId?string
billingPeriodId?string

Header Parameters

X-Client-Id?string

Scope results to one client (brand). Resolve a client name to its id via GET /api/clients/lookup. Validated against the credential's tenant; ignored by a client-pinned credential.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/invoices"
{  "success": true,  "data": [    {      "id": "string",      "tenantId": "string",      "clientId": "string",      "billingPeriodId": "string",      "invoiceNumber": "string",      "totalAmount": 0,      "currency": "string",      "generatedAt": "2019-08-24T14:15:22Z",      "sentAt": "2019-08-24T14:15:22Z"    }  ],  "pagination": {    "page": 0,    "limit": 0,    "total": 0,    "totalPages": 0  }}
GET
/api/billing/invoices/{id}

The invoice, with time-limited signed download URLs where object storage holds the rendered files. A client-pinned credential gets null URLs: use /download.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Path Parameters

id*string

Invoice id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/invoices/string"
{  "success": true,  "data": {    "id": "string",    "tenantId": "string",    "clientId": "string",    "billingPeriodId": "string",    "invoiceNumber": "string",    "totalAmount": 0,    "currency": "string",    "generatedAt": "2019-08-24T14:15:22Z",    "sentAt": "2019-08-24T14:15:22Z",    "csvSignedUrl": "string",    "pdfSignedUrl": "string",    "signedUrlsExpireAt": "2019-08-24T14:15:22Z"  }}
GET
/api/billing/invoices/{id}/signed-urls

Fresh 7-day signed URLs for the stored CSV and PDF. Null for a client-pinned credential and when object storage is not configured; /download always works.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Path Parameters

id*string

Invoice id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/invoices/string/signed-urls"
{  "success": true,  "data": {    "invoiceId": "string",    "csvSignedUrl": "string",    "pdfSignedUrl": "string",    "expiresAt": "2019-08-24T14:15:22Z"  }}
GET
/api/billing/invoices/{id}/download

Re-renders the invoice on demand and streams it as an attachment. A client-pinned credential receives the client projection: bin-storage lines read "Storage fee" and name no bin.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Path Parameters

id*string

Invoice id

Query Parameters

format*string

Value in

  • "csv"
  • "pdf"

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/invoices/string/download?format=csv"
"string"
GET
/api/billing/charges

Every charge in scope, newest occurrence first; filter by billingPeriodId to read one period's lines. A client-pinned credential sees the client view (the schema description lists the staff-only fields it does not receive).

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Query Parameters

clientId?string
billingPeriodId?string
category?string

Value in

  • "PICK"
  • "LABEL"
  • "RECEIVING_PALLET"
  • "RECEIVING_CARTON"
  • "STORAGE_PALLET"
  • "STORAGE_BIN"
  • "RETURN_PROCESSING"
  • "AD_HOC"
  • "SHIPPING_RECONCILIATION"
  • "ORDER_FEES"
  • "RECEIVING_FEES"
  • "RETURN_FEES"
status?string

Value in

  • "ACTIVE"
  • "VOIDED"
sourceType?string

Value in

  • "SHIPMENT"
  • "PACK_RECORD"
  • "ORDER"
  • "ORDER_LINE"
  • "INBOUND_SHIPMENT"
  • "PALLET"
  • "BIN"
  • "RETURN"
  • "AD_HOC"
  • "RECURRING"
  • "MANUAL"

Header Parameters

X-Client-Id?string

Scope results to one client (brand). Resolve a client name to its id via GET /api/clients/lookup. Validated against the credential's tenant; ignored by a client-pinned credential.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/charges"
{  "success": true,  "data": [    {      "id": "string",      "clientId": "string",      "billingPeriodId": "string",      "category": "PICK",      "description": "string",      "quantity": 0,      "unitPrice": 0,      "multiplier": 0,      "amount": 0,      "currency": "string",      "status": "ACTIVE",      "approvalStatus": "PENDING",      "sourceType": "SHIPMENT",      "sourceId": "string",      "adHocChargeTypeId": "string",      "occurredAt": "2019-08-24T14:15:22Z",      "generatedAt": "2019-08-24T14:15:22Z",      "orderNumber": "string"    }  ]}
GET
/api/billing/adjustments

Signed amounts: a negative adjustment is a credit. A client-pinned credential sees the client view.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Query Parameters

clientId?string
billingPeriodId?string
category?string

Value in

  • "PICK"
  • "LABEL"
  • "RECEIVING_PALLET"
  • "RECEIVING_CARTON"
  • "STORAGE_PALLET"
  • "STORAGE_BIN"
  • "RETURN_PROCESSING"
  • "AD_HOC"
  • "SHIPPING_RECONCILIATION"
  • "ORDER_FEES"
  • "RECEIVING_FEES"
  • "RETURN_FEES"
appliesToId?string

Header Parameters

X-Client-Id?string

Scope results to one client (brand). Resolve a client name to its id via GET /api/clients/lookup. Validated against the credential's tenant; ignored by a client-pinned credential.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/adjustments"
{  "success": true,  "data": [    {      "id": "string",      "clientId": "string",      "billingPeriodId": "string",      "chargeId": "string",      "category": "PICK",      "amount": 0,      "description": "string",      "appliesToType": "SHIPMENT",      "appliesToId": "string",      "origin": "MANUAL",      "createdAt": "2019-08-24T14:15:22Z"    }  ]}
GET
/api/billing/periods

Newest first, each with its running charges total. A period is OPEN while events accrue, then moves through CLOSING and FINALIZED to INVOICED.

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Query Parameters

clientId?string
status?string

Value in

  • "OPEN"
  • "CLOSING"
  • "FINALIZED"
  • "INVOICED"

Header Parameters

X-Client-Id?string

Scope results to one client (brand). Resolve a client name to its id via GET /api/clients/lookup. Validated against the credential's tenant; ignored by a client-pinned credential.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/periods"
{  "success": true,  "data": [    {      "id": "string",      "tenantId": "string",      "clientId": "string",      "startDate": "2019-08-24T14:15:22Z",      "endDate": "2019-08-24T14:15:22Z",      "status": "OPEN",      "currency": "string",      "finalizedAt": "2019-08-24T14:15:22Z",      "createdAt": "2019-08-24T14:15:22Z",      "updatedAt": "2019-08-24T14:15:22Z",      "chargesTotal": 0    }  ]}
GET
/api/billing/periods/{id}

Authorization

oauth2 billing:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: billing:read

Path Parameters

id*string

Billing period id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/periods/string"
{  "success": true,  "data": {    "id": "string",    "tenantId": "string",    "clientId": "string",    "startDate": "2019-08-24T14:15:22Z",    "endDate": "2019-08-24T14:15:22Z",    "status": "OPEN",    "currency": "string",    "finalizedAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z",    "chargesTotal": 0  }}
GET
/api/billing/rate-cards

Tenant-wide credentials only. A credential pinned to one client is refused (403), as that client's portal users are; use a tenant-wide credential with X-Client-Id. Drafts (isActive: false) are included; deleted cards are not.

Authorization

oauth2 rate-cards:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: rate-cards:read

Header Parameters

X-Client-Id?string

Scope results to one client (brand). Resolve a client name to its id via GET /api/clients/lookup. Validated against the credential's tenant; ignored by a client-pinned credential.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/rate-cards"
{  "success": true,  "data": [    {      "id": "string",      "tenantId": "string",      "clientId": "string",      "name": "string",      "effectiveFrom": "2019-08-24T14:15:22Z",      "effectiveTo": "2019-08-24T14:15:22Z",      "chargeShippingLabels": true,      "isActive": true,      "deletedAt": "2019-08-24T14:15:22Z",      "createdAt": "2019-08-24T14:15:22Z",      "updatedAt": "2019-08-24T14:15:22Z"    }  ]}
GET
/api/billing/rate-cards/{id}

Tenant-wide credentials only. A credential pinned to one client is refused (403), as that client's portal users are; use a tenant-wide credential with X-Client-Id. Rules are ordered by category, then priority.

Authorization

oauth2 rate-cards:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: rate-cards:read

Path Parameters

id*string

Rate card id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/rate-cards/string"
{  "success": true,  "data": {    "id": "string",    "tenantId": "string",    "clientId": "string",    "name": "string",    "effectiveFrom": "2019-08-24T14:15:22Z",    "effectiveTo": "2019-08-24T14:15:22Z",    "chargeShippingLabels": true,    "isActive": true,    "deletedAt": "2019-08-24T14:15:22Z",    "createdAt": "2019-08-24T14:15:22Z",    "updatedAt": "2019-08-24T14:15:22Z",    "rules": [      {        "id": "string",        "rateCardId": "string",        "category": "PICK",        "shape": "FLAT",        "name": "string",        "config": null,        "selector": null,        "selectorKey": "string",        "priority": 0,        "isActive": true,        "sharedRuleId": "string",        "deletedAt": "2019-08-24T14:15:22Z",        "createdAt": "2019-08-24T14:15:22Z",        "updatedAt": "2019-08-24T14:15:22Z"      }    ]  }}
GET
/api/billing/rate-cards/{id}/versions

Tenant-wide credentials only. A credential pinned to one client is refused (403), as that client's portal users are; use a tenant-wide credential with X-Client-Id. The published cards that succeed one another without a gap, around the requested card.

Authorization

oauth2 rate-cards:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: rate-cards:read

Path Parameters

id*string

Rate card id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/rate-cards/string/versions"
{  "success": true,  "data": {    "cardId": "string",    "clientId": "string",    "versions": [      {        "id": "string",        "name": "string",        "effectiveFrom": "2019-08-24T14:15:22Z",        "effectiveTo": "2019-08-24T14:15:22Z",        "isCurrent": true,        "isRequestedCard": true,        "activeRuleCount": 0,        "mintedByCorrection": true      }    ]  }}
GET
/api/billing/rate-cards/{id}/rules/{ruleId}/history

Tenant-wide credentials only. A credential pinned to one client is refused (403), as that client's portal users are; use a tenant-wide credential with X-Client-Id. The last 100 edits to one rule, newest first, with the unit price before and after each.

Authorization

oauth2 rate-cards:read
AuthorizationBearer <token>

OAuth2 client-credentials grant.

In: header

Scope: rate-cards:read

Path Parameters

id*string

Rate card id

ruleId*string

Rule id

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/api/billing/rate-cards/string/rules/string/history"
{  "success": true,  "data": [    {      "id": "string",      "action": "string",      "sharedRuleId": "string",      "performedByEmail": "string",      "createdAt": "2019-08-24T14:15:22Z",      "previousUnitPrice": 0,      "newUnitPrice": 0,      "previousValue": null,      "newValue": null    }  ]}