@maxio-com/advanced-billing-sdk
Version:
Ultimate billing and pricing flexibility for B2B SaaS. Maxio integrates directly into your product, so you can seamlessly manage your product catalog, bill customers, and collect payments.
1,150 lines (1,131 loc) • 50 kB
text/typescript
/**
* AdvancedBilling
*
* This file was automatically generated for Maxio by APIMATIC v3.0 ( https://www.apimatic.io ).
*/
import { ApiResponse, commaPrefix, RequestOptions } from '../core';
import {
ConsolidatedInvoice,
consolidatedInvoiceSchema,
} from '../models/consolidatedInvoice';
import {
CreateInvoicePaymentRequest,
createInvoicePaymentRequestSchema,
} from '../models/createInvoicePaymentRequest';
import {
CreateInvoiceRequest,
createInvoiceRequestSchema,
} from '../models/createInvoiceRequest';
import {
CreateMultiInvoicePaymentRequest,
createMultiInvoicePaymentRequestSchema,
} from '../models/createMultiInvoicePaymentRequest';
import { CreditNote, creditNoteSchema } from '../models/creditNote';
import {
CustomerChangesPreviewResponse,
customerChangesPreviewResponseSchema,
} from '../models/customerChangesPreviewResponse';
import { Direction, directionSchema } from '../models/direction';
import { Invoice, invoiceSchema } from '../models/invoice';
import {
InvoiceDateField,
invoiceDateFieldSchema,
} from '../models/invoiceDateField';
import {
InvoiceEventType,
invoiceEventTypeSchema,
} from '../models/invoiceEventType';
import {
InvoiceResponse,
invoiceResponseSchema,
} from '../models/invoiceResponse';
import {
InvoiceSortField,
invoiceSortFieldSchema,
} from '../models/invoiceSortField';
import { InvoiceStatus, invoiceStatusSchema } from '../models/invoiceStatus';
import {
IssueInvoiceRequest,
issueInvoiceRequestSchema,
} from '../models/issueInvoiceRequest';
import {
ListCreditNotesResponse,
listCreditNotesResponseSchema,
} from '../models/listCreditNotesResponse';
import {
ListInvoiceEventsResponse,
listInvoiceEventsResponseSchema,
} from '../models/listInvoiceEventsResponse';
import {
ListInvoicesResponse,
listInvoicesResponseSchema,
} from '../models/listInvoicesResponse';
import {
MultiInvoicePaymentResponse,
multiInvoicePaymentResponseSchema,
} from '../models/multiInvoicePaymentResponse';
import {
RecordPaymentRequest,
recordPaymentRequestSchema,
} from '../models/recordPaymentRequest';
import {
RecordPaymentResponse,
recordPaymentResponseSchema,
} from '../models/recordPaymentResponse';
import {
RefundInvoiceRequest,
refundInvoiceRequestSchema,
} from '../models/refundInvoiceRequest';
import {
SendInvoiceRequest,
sendInvoiceRequestSchema,
} from '../models/sendInvoiceRequest';
import {
VoidInvoiceRequest,
voidInvoiceRequestSchema,
} from '../models/voidInvoiceRequest';
import { array, bigint, boolean, number, optional, string } from '../schema';
import { BaseController } from './baseController';
import { ApiError } from '@apimatic/core';
import { ErrorArrayMapResponseError } from '../errors/errorArrayMapResponseError';
import { ErrorListResponseError } from '../errors/errorListResponseError';
export class InvoicesController extends BaseController {
/**
* Refund an invoice, segment, or consolidated invoice.
*
* ## Partial Refund for Consolidated Invoice
*
* A refund less than the total of a consolidated invoice will be split across its segments.
*
* A $50.00 refund on a $100.00 consolidated invoice with one $60.00 and one $40.00 segment, the
* refunded amount will be applied as 50% of each ($30.00 and $20.00 respectively).
*
* @param uid The unique identifier for the invoice, this does not refer to
* the public facing invoice number.
* @param body
* @return Response from the API call
*/
async refundInvoice(
uid: string,
body?: RefundInvoiceRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
uid: [uid, string()],
body: [body, optional(refundInvoiceRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/invoices/${mapped.uid}/refunds.json`;
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* By default, invoices returned on the index will only include totals, not detailed breakdowns for
* `line_items`, `discounts`, `taxes`, `credits`, `payments`, `custom_fields`, or `refunds`. To include
* breakdowns, pass the specific field as a key in the query with a value set to `true`.
*
* @param startDate The start date (format YYYY-MM-DD) with which to filter the
* date_field. Returns invoices with a timestamp at or after
* midnight (12:00:00 AM) in your site’s time zone on the date
* specified.
* @param endDate The end date (format YYYY-MM-DD) with which to filter the
* date_field. Returns invoices with a timestamp up to and
* including 11:59:59PM in your site’s time zone on the date
* specified.
* @param status The current status of the invoice. Allowed Values: draft, open,
* paid, pending, voided
* @param subscriptionId The subscription's ID.
* @param subscriptionGroupUid The UID of the subscription group you want to fetch
* consolidated invoices for. This will return a paginated list of
* consolidated invoices for the specified group.
* @param consolidationLevel The consolidation level of the invoice. Allowed Values: none,
* parent, child or comma-separated lists of thereof, e.g. none,
* parent.
* @param page Result records are organized in pages. By default, the first
* page of results is displayed. The page parameter specifies a
* page number of results to fetch. You can start navigating
* through the pages to consume the results. You do this by passing
* in a page parameter. Retrieve the next page by adding ?page=2 to
* the query string. If there are no results to return, then an
* empty result set will be returned. Use in query `page=1`.
* @param perPage This parameter indicates how many records to fetch in each
* request. Default value is 20. The maximum allowed values is 200;
* any per_page value over 200 will be changed to 200. Use in query
* `per_page=200`.
* @param direction The sort direction of the returned invoices.
* @param lineItems Include line items data
* @param discounts Include discounts data
* @param taxes Include taxes data
* @param credits Include credits data
* @param payments Include payments data
* @param customFields Include custom fields data
* @param refunds Include refunds data
* @param dateField The type of filter you would like to apply to your search. Use
* in query `date_field=issue_date`.
* @param startDatetime The start date and time (format YYYY-MM-DD HH:MM:SS) with which
* to filter the date_field. Returns invoices with a timestamp at
* or after exact time provided in query. You can specify timezone
* in query - otherwise your site's time zone will be used. If
* provided, this parameter will be used instead of start_date.
* Allowed to be used only along with date_field set to created_at
* or updated_at.
* @param endDatetime The end date and time (format YYYY-MM-DD HH:MM:SS) with which
* to filter the date_field. Returns invoices with a timestamp at
* or before exact time provided in query. You can specify timezone
* in query - otherwise your site's time zone will be used. If
* provided, this parameter will be used instead of end_date.
* Allowed to be used only along with date_field set to created_at
* or updated_at.
* @param customerIds Allows fetching invoices with matching customer id based on
* provided values. Use in query `customer_ids=1,2,3`.
* @param number Allows fetching invoices with matching invoice number based on
* provided values. Use in query `number=1234,1235`.
* @param productIds Allows fetching invoices with matching line items product ids
* based on provided values. Use in query `product_ids=23,34`.
* @param sort Allows specification of the order of the returned list. Use in
* query `sort=total_amount`.
* @return Response from the API call
*/
async listInvoices(
{
startDate,
endDate,
status,
subscriptionId,
subscriptionGroupUid,
consolidationLevel,
page,
perPage,
direction,
lineItems,
discounts,
taxes,
credits,
payments,
customFields,
refunds,
dateField,
startDatetime,
endDatetime,
customerIds,
mNumber,
productIds,
sort,
}: {
startDate?: string;
endDate?: string;
status?: InvoiceStatus;
subscriptionId?: number;
subscriptionGroupUid?: string;
consolidationLevel?: string;
page?: number;
perPage?: number;
direction?: Direction;
lineItems?: boolean;
discounts?: boolean;
taxes?: boolean;
credits?: boolean;
payments?: boolean;
customFields?: boolean;
refunds?: boolean;
dateField?: InvoiceDateField;
startDatetime?: string;
endDatetime?: string;
customerIds?: number[];
mNumber?: string[];
productIds?: number[];
sort?: InvoiceSortField;
},
requestOptions?: RequestOptions
): Promise<ApiResponse<ListInvoicesResponse>> {
const req = this.createRequest('GET', '/invoices.json');
const mapped = req.prepareArgs({
startDate: [startDate, optional(string())],
endDate: [endDate, optional(string())],
status: [status, optional(invoiceStatusSchema)],
subscriptionId: [subscriptionId, optional(number())],
subscriptionGroupUid: [subscriptionGroupUid, optional(string())],
consolidationLevel: [consolidationLevel, optional(string())],
page: [page, optional(number())],
perPage: [perPage, optional(number())],
direction: [direction, optional(directionSchema)],
lineItems: [lineItems, optional(boolean())],
discounts: [discounts, optional(boolean())],
taxes: [taxes, optional(boolean())],
credits: [credits, optional(boolean())],
payments: [payments, optional(boolean())],
customFields: [customFields, optional(boolean())],
refunds: [refunds, optional(boolean())],
dateField: [dateField, optional(invoiceDateFieldSchema)],
startDatetime: [startDatetime, optional(string())],
endDatetime: [endDatetime, optional(string())],
customerIds: [customerIds, optional(array(number()))],
mNumber: [mNumber, optional(array(string()))],
productIds: [productIds, optional(array(number()))],
sort: [sort, optional(invoiceSortFieldSchema)],
});
req.query('start_date', mapped.startDate, commaPrefix);
req.query('end_date', mapped.endDate, commaPrefix);
req.query('status', mapped.status, commaPrefix);
req.query('subscription_id', mapped.subscriptionId, commaPrefix);
req.query(
'subscription_group_uid',
mapped.subscriptionGroupUid,
commaPrefix
);
req.query('consolidation_level', mapped.consolidationLevel, commaPrefix);
req.query('page', mapped.page, commaPrefix);
req.query('per_page', mapped.perPage, commaPrefix);
req.query('direction', mapped.direction, commaPrefix);
req.query('line_items', mapped.lineItems, commaPrefix);
req.query('discounts', mapped.discounts, commaPrefix);
req.query('taxes', mapped.taxes, commaPrefix);
req.query('credits', mapped.credits, commaPrefix);
req.query('payments', mapped.payments, commaPrefix);
req.query('custom_fields', mapped.customFields, commaPrefix);
req.query('refunds', mapped.refunds, commaPrefix);
req.query('date_field', mapped.dateField, commaPrefix);
req.query('start_datetime', mapped.startDatetime, commaPrefix);
req.query('end_datetime', mapped.endDatetime, commaPrefix);
req.query('customer_ids', mapped.customerIds, commaPrefix);
req.query('number', mapped.mNumber, commaPrefix);
req.query('product_ids', mapped.productIds, commaPrefix);
req.query('sort', mapped.sort, commaPrefix);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(listInvoicesResponseSchema, requestOptions);
}
/**
* Use this endpoint to retrieve the details for an invoice.
*
* ## PDF Invoice retrieval
*
* Individual PDF Invoices can be retrieved by using the "Accept" header application/pdf or appending .
* pdf as the format portion of the URL:
* ```curl -u <api_key>:x -H
* Accept:application/pdf -H
* https://acme.chargify.com/invoices/inv_8gd8tdhtd3hgr.pdf > output_file.pdf
* URL: `https://<subdomain>.chargify.com/invoices/<uid>.<format>`
* Method: GET
* Required parameters: `uid`
* Response: A single Invoice.
* ```
*
* @param uid The unique identifier for the invoice, this does not refer to the public facing invoice
* number.
* @return Response from the API call
*/
async readInvoice(
uid: string,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('GET');
const mapped = req.prepareArgs({ uid: [uid, string()] });
req.appendTemplatePath`/invoices/${mapped.uid}.json`;
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* This endpoint returns a list of invoice events. Each event contains event "data" (such as an applied
* payment) as well as a snapshot of the `invoice` at the time of event completion.
*
* Exposed event types are:
*
* + issue_invoice
* + apply_credit_note
* + apply_payment
* + refund_invoice
* + void_invoice
* + void_remainder
* + backport_invoice
* + change_invoice_status
* + change_invoice_collection_method
* + remove_payment
* + failed_payment
* + apply_debit_note
* + create_debit_note
* + change_chargeback_status
*
* Invoice events are returned in ascending order.
*
* If both a `since_date` and `since_id` are provided in request parameters, the `since_date` will be
* used.
*
* Note - invoice events that occurred prior to 09/05/2018 __will not__ contain an `invoice` snapshot.
*
* @param sinceDate The timestamp in a format `YYYY-MM-DD T HH:MM:SS Z`, or
* `YYYY-MM-DD`(in this case, it returns data from the
* beginning of the day). of the event from which you want to
* start the search. All the events before the `since_date`
* timestamp are not returned in the response.
* @param sinceId The ID of the event from which you want to start the
* search(ID is not included. e.g. if ID is set to 2, then
* all events with ID 3 and more will be shown) This
* parameter is not used if since_date is defined.
* @param page Result records are organized in pages. By default, the
* first page of results is displayed. The page parameter
* specifies a page number of results to fetch. You can start
* navigating through the pages to consume the results. You
* do this by passing in a page parameter. Retrieve the next
* page by adding ?page=2 to the query string. If there are
* no results to return, then an empty result set will be
* returned. Use in query `page=1`.
* @param perPage This parameter indicates how many records to fetch in
* each request. Default value is 100. The maximum allowed
* values is 200; any per_page value over 200 will be changed
* to 200.
* @param invoiceUid Providing an invoice_uid allows for scoping of the
* invoice events to a single invoice or credit note.
* @param withChangeInvoiceStatus Use this parameter if you want to fetch also invoice
* events with change_invoice_status type.
* @param eventTypes Filter results by event_type. Supply a comma separated
* list of event types (listed above). Use in query:
* `event_types=void_invoice,void_remainder`.
* @return Response from the API call
*/
async listInvoiceEvents(
{
sinceDate,
sinceId,
page,
perPage,
invoiceUid,
withChangeInvoiceStatus,
eventTypes,
}: {
sinceDate?: string;
sinceId?: bigint;
page?: number;
perPage?: number;
invoiceUid?: string;
withChangeInvoiceStatus?: string;
eventTypes?: InvoiceEventType[];
},
requestOptions?: RequestOptions
): Promise<ApiResponse<ListInvoiceEventsResponse>> {
const req = this.createRequest('GET', '/invoices/events.json');
const mapped = req.prepareArgs({
sinceDate: [sinceDate, optional(string())],
sinceId: [sinceId, optional(bigint())],
page: [page, optional(number())],
perPage: [perPage, optional(number())],
invoiceUid: [invoiceUid, optional(string())],
withChangeInvoiceStatus: [withChangeInvoiceStatus, optional(string())],
eventTypes: [eventTypes, optional(array(invoiceEventTypeSchema))],
});
req.query('since_date', mapped.sinceDate, commaPrefix);
req.query('since_id', mapped.sinceId, commaPrefix);
req.query('page', mapped.page, commaPrefix);
req.query('per_page', mapped.perPage, commaPrefix);
req.query('invoice_uid', mapped.invoiceUid, commaPrefix);
req.query(
'with_change_invoice_status',
mapped.withChangeInvoiceStatus,
commaPrefix
);
req.query('event_types', mapped.eventTypes, commaPrefix);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(listInvoiceEventsResponseSchema, requestOptions);
}
/**
* Applies a payment of a given type against a specific invoice. If you would like to apply a payment
* across multiple invoices, you can use the Bulk Payment endpoint.
*
* @param uid The unique identifier for the invoice, this does not
* refer to the public facing invoice number.
* @param body
* @return Response from the API call
*/
async recordPaymentForInvoice(
uid: string,
body?: CreateInvoicePaymentRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
uid: [uid, string()],
body: [body, optional(createInvoicePaymentRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/invoices/${mapped.uid}/payments.json`;
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* This API call should be used when you want to record an external payment against multiple invoices.
*
* In order apply a payment to multiple invoices, at minimum, specify the `amount` and `applications`
* (i.e., `invoice_uid` and `amount`) details.
*
* ```
* {
* "payment": {
* "memo": "to pay the bills",
* "details": "check number 8675309",
* "method": "check",
* "amount": "250.00",
* "applications": [
* {
* "invoice_uid": "inv_8gk5bwkct3gqt",
* "amount": "100.00"
* },
* {
* "invoice_uid": "inv_7bc6bwkct3lyt",
* "amount": "150.00"
* }
* ]
* }
* }
* ```
*
* Note that the invoice payment amounts must be greater than 0. Total amount must be greater or equal
* to invoices payment amount sum.
*
* @param body
* @return Response from the API call
*/
async recordPaymentForMultipleInvoices(
body?: CreateMultiInvoicePaymentRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<MultiInvoicePaymentResponse>> {
const req = this.createRequest('POST', '/invoices/payments.json');
const mapped = req.prepareArgs({
body: [body, optional(createMultiInvoicePaymentRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(multiInvoicePaymentResponseSchema, requestOptions);
}
/**
* Credit Notes are like inverse invoices. They reduce the amount a customer owes.
*
* By default, the credit notes returned by this endpoint will exclude the arrays of `line_items`,
* `discounts`, `taxes`, `applications`, or `refunds`. To include these arrays, pass the specific field
* as a key in the query with a value set to `true`.
*
* @param subscriptionId The subscription's Advanced Billing id
* @param page Result records are organized in pages. By default, the first page of results is
* displayed. The page parameter specifies a page number of results to fetch. You
* can start navigating through the pages to consume the results. You do this by
* passing in a page parameter. Retrieve the next page by adding ?page=2 to the
* query string. If there are no results to return, then an empty result set will
* be returned. Use in query `page=1`.
* @param perPage This parameter indicates how many records to fetch in each request. Default
* value is 20. The maximum allowed values is 200; any per_page value over 200 will
* be changed to 200. Use in query `per_page=200`.
* @param lineItems Include line items data
* @param discounts Include discounts data
* @param taxes Include taxes data
* @param refunds Include refunds data
* @param applications Include applications data
* @return Response from the API call
*/
async listCreditNotes(
{
subscriptionId,
page,
perPage,
lineItems,
discounts,
taxes,
refunds,
applications,
}: {
subscriptionId?: number;
page?: number;
perPage?: number;
lineItems?: boolean;
discounts?: boolean;
taxes?: boolean;
refunds?: boolean;
applications?: boolean;
},
requestOptions?: RequestOptions
): Promise<ApiResponse<ListCreditNotesResponse>> {
const req = this.createRequest('GET', '/credit_notes.json');
const mapped = req.prepareArgs({
subscriptionId: [subscriptionId, optional(number())],
page: [page, optional(number())],
perPage: [perPage, optional(number())],
lineItems: [lineItems, optional(boolean())],
discounts: [discounts, optional(boolean())],
taxes: [taxes, optional(boolean())],
refunds: [refunds, optional(boolean())],
applications: [applications, optional(boolean())],
});
req.query('subscription_id', mapped.subscriptionId, commaPrefix);
req.query('page', mapped.page, commaPrefix);
req.query('per_page', mapped.perPage, commaPrefix);
req.query('line_items', mapped.lineItems, commaPrefix);
req.query('discounts', mapped.discounts, commaPrefix);
req.query('taxes', mapped.taxes, commaPrefix);
req.query('refunds', mapped.refunds, commaPrefix);
req.query('applications', mapped.applications, commaPrefix);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(listCreditNotesResponseSchema, requestOptions);
}
/**
* Use this endpoint to retrieve the details for a credit note.
*
* @param uid The unique identifier of the credit note
* @return Response from the API call
*/
async readCreditNote(
uid: string,
requestOptions?: RequestOptions
): Promise<ApiResponse<CreditNote>> {
const req = this.createRequest('GET');
const mapped = req.prepareArgs({ uid: [uid, string()] });
req.appendTemplatePath`/credit_notes/${mapped.uid}.json`;
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(creditNoteSchema, requestOptions);
}
/**
* Record an external payment made against a subscription that will pay partially or in full one or
* more invoices.
*
* Payment will be applied starting with the oldest open invoice and then next oldest, and so on until
* the amount of the payment is fully consumed.
*
* Excess payment will result in the creation of a prepayment on the Invoice Account.
*
* Only ungrouped or primary subscriptions may be paid using the "bulk" payment request.
*
* @param subscriptionId The Chargify id of the subscription
* @param body
* @return Response from the API call
*/
async recordPaymentForSubscription(
subscriptionId: number,
body?: RecordPaymentRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<RecordPaymentResponse>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
subscriptionId: [subscriptionId, number()],
body: [body, optional(recordPaymentRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/subscriptions/${mapped.subscriptionId}/payments.json`;
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(recordPaymentResponseSchema, requestOptions);
}
/**
* This endpoint allows you to reopen any invoice with the "canceled" status. Invoices enter "canceled"
* status if they were open at the time the subscription was canceled (whether through dunning or an
* intentional cancellation).
*
* Invoices with "canceled" status are no longer considered to be due. Once reopened, they are
* considered due for payment. Payment may then be captured in one of the following ways:
*
* - Reactivating the subscription, which will capture all open invoices (See note below about
* automatic reopening of invoices.)
* - Recording a payment directly against the invoice
*
* A note about reactivations: any canceled invoices from the most recent active period are
* automatically opened as a part of the reactivation process. Reactivating via this endpoint prior to
* reactivation is only necessary when you wish to capture older invoices from previous periods during
* the reactivation.
*
* ### Reopening Consolidated Invoices
*
* When reopening a consolidated invoice, all of its canceled segments will also be reopened.
*
* @param uid The unique identifier for the invoice, this does not refer to the public facing invoice
* number.
* @return Response from the API call
*/
async reopenInvoice(
uid: string,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({ uid: [uid, string()] });
req.appendTemplatePath`/invoices/${mapped.uid}/reopen.json`;
req.throwOn(404, ApiError, true, "Not Found:'{$response.body}'");
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* This endpoint allows you to void any invoice with the "open" or "canceled" status. It will also
* allow voiding of an invoice with the "pending" status if it is not a consolidated invoice.
*
* @param uid The unique identifier for the invoice, this does not refer to
* the public facing invoice number.
* @param body
* @return Response from the API call
*/
async voidInvoice(
uid: string,
body?: VoidInvoiceRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
uid: [uid, string()],
body: [body, optional(voidInvoiceRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/invoices/${mapped.uid}/void.json`;
req.throwOn(404, ApiError, true, "Not Found:'{$response.body}'");
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* Invoice segments returned on the index will only include totals, not detailed breakdowns for
* `line_items`, `discounts`, `taxes`, `credits`, `payments`, or `custom_fields`.
*
* @param invoiceUid The unique identifier of the consolidated invoice
* @param page Result records are organized in pages. By default, the first page of results is
* displayed. The page parameter specifies a page number of results to fetch. You can
* start navigating through the pages to consume the results. You do this by passing
* in a page parameter. Retrieve the next page by adding ?page=2 to the query string.
* If there are no results to return, then an empty result set will be returned. Use
* in query `page=1`.
* @param perPage This parameter indicates how many records to fetch in each request. Default value
* is 20. The maximum allowed values is 200; any per_page value over 200 will be
* changed to 200. Use in query `per_page=200`.
* @param direction Sort direction of the returned segments.
* @return Response from the API call
*/
async listConsolidatedInvoiceSegments(
{
invoiceUid,
page,
perPage,
direction,
}: {
invoiceUid: string;
page?: number;
perPage?: number;
direction?: Direction;
},
requestOptions?: RequestOptions
): Promise<ApiResponse<ConsolidatedInvoice>> {
const req = this.createRequest('GET');
const mapped = req.prepareArgs({
invoiceUid: [invoiceUid, string()],
page: [page, optional(number())],
perPage: [perPage, optional(number())],
direction: [direction, optional(directionSchema)],
});
req.query('page', mapped.page, commaPrefix);
req.query('per_page', mapped.perPage, commaPrefix);
req.query('direction', mapped.direction, commaPrefix);
req.appendTemplatePath`/invoices/${mapped.invoiceUid}/segments.json`;
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(consolidatedInvoiceSchema, requestOptions);
}
/**
* This endpoint will allow you to create an ad hoc invoice.
*
* ### Basic Behavior
*
* You can create a basic invoice by sending an array of line items to this endpoint. Each line item,
* at a minimum, must include a title, a quantity and a unit price. Example:
*
* ```json
* {
* "invoice": {
* "line_items": [
* {
* "title": "A Product",
* "quantity": 12,
* "unit_price": "150.00"
* }
* ]
* }
* }
* ```
*
* ### Catalog items
* Instead of creating custom products like in above example, You can pass existing items like products,
* components.
*
* ```json
* {
* "invoice": {
* "line_items": [
* {
* "product_id": "handle:gold-product",
* "quantity": 2,
* }
* ]
* }
* }
* ```
*
*
* The price for each line item will be calculated as well as a total due amount for the invoice.
* Multiple line items can be sent.
*
* ### Line items types
* When defining line item, You can choose one of 3 types for one line item:
* #### Custom item
* Like in basic behavior example above, You can pass `title` and `unit_price` for custom item.
* #### Product id
* Product handle (with handle: prefix) or id from the scope of current subscription's site can be
* provided with `product_id`. By default `unit_price` is taken from product's default price point, but
* can be overwritten by passing `unit_price` or `product_price_point_id`. If `product_id` is used,
* following fields cannot be used: `title`, `component_id`.
* #### Component id
* Component handle (with handle: prefix) or id from the scope of current subscription's site can be
* provided with `component_id`. If `component_id` is used, following fields cannot be used: `title`,
* `product_id`. By default `unit_price` is taken from product's default price point, but can be
* overwritten by passing `unit_price` or `price_point_id`. At this moment price points are supportted
* only for quantity based, on/off and metered components. For prepaid and event based billing
* components `unit_price` is required.
*
* ### Coupons
* When creating ad hoc invoice, new discounts can be applied in following way:
*
* ```json
* {
* "invoice": {
* "line_items": [
* {
* "product_id": "handle:gold-product",
* "quantity": 1
* }
* ],
* "coupons": [
* {
* "code": "COUPONCODE",
* "percentage": 50.0
* }
* ]
* }
* }
* ```
* If You want to use existing coupon for discount creation, only `code` and optional
* `product_family_id` is needed
*
* ```json
* ...
* "coupons": [
* {
* "code": "FREESETUP",
* "product_family_id": 1
* }
* ]
* ...
* ```
*
* ### Coupon options
* #### Code
* Coupon `code` will be displayed on invoice discount section.
* Coupon code can only contain uppercase letters, numbers, and allowed special characters.
* Lowercase letters will be converted to uppercase. It can be used to select an existing coupon from
* the catalog, or as an ad hoc coupon when passed with `percentage` or `amount`.
* #### Percentage
* Coupon `percentage` can take values from 0 to 100 and up to 4 decimal places. It cannot be used with
* `amount`. Only for ad hoc coupons, will be ignored if `code` is used to select an existing coupon
* from the catalog.
* #### Amount
* Coupon `amount` takes number value. It cannot be used with `percentage`. Used only when not matching
* existing coupon by `code`.
* #### Description
* Optional `description` will be displayed with coupon `code`. Used only when not matching existing
* coupon by `code`.
* #### Product Family id
* Optional `product_family_id` handle (with handle: prefix) or id is used to match existing coupon
* within site, when codes are not unique.
* #### Compounding Strategy
* Optional `compounding_strategy` for percentage coupons, can take values `compound` or `full-price`.
*
* For amount coupons, discounts will be always calculated against the original item price, before
* other discounts are applied.
*
* `compound` strategy:
* Percentage-based discounts will be calculated against the remaining price, after prior discounts
* have been calculated. It is set by default.
*
* `full-price` strategy:
* Percentage-based discounts will always be calculated against the original item price, before other
* discounts are applied.
*
* ### Line Item Options
*
* #### Period Date Range
*
* A custom period date range can be defined for each line item with the `period_range_start` and
* `period_range_end` parameters. Dates must be sent in the `YYYY-MM-DD` format.
* `period_range_end` must be greater or equal `period_range_start`.
*
* #### Taxes
*
* The `taxable` parameter can be sent as `true` if taxes should be calculated for a specific line item.
* For this to work, the site should be configured to use and calculate taxes. Further, if the site
* uses Avalara for tax calculations, a `tax_code` parameter should also be sent. For existing catalog
* items: products/components taxes cannot be overwritten.
*
* #### Price Point
* Price point handle (with handle: prefix) or id from the scope of current subscription's site can be
* provided with `price_point_id` for components with `component_id` or `product_price_point_id` for
* products with `product_id` parameter. If price point is passed `unit_price` cannot be used. It can
* be used only with catalog items products and components.
*
* #### Description
* Optional `description` parameter, it will overwrite default generated description for line item.
*
* ### Invoice Options
*
* #### Issue Date
*
* By default, invoices will be created with a issue date set to today. `issue_date` parameter can be
* send to alter that. Only dates in the past can be send. `issue_date` should be send in `YYYY-MM-DD`
* format.
*
* #### Net Terms
*
* By default, invoices will be created with a due date matching the date of invoice creation. If a
* different due date is desired, the `net_terms` parameter can be sent indicating the number of days
* in advance the due date should be.
*
* #### Addresses
*
* The seller, shipping and billing addresses can be sent to override the site's defaults. Each address
* requires to send a `first_name` at a minimum in order to work. Please see below for the details on
* which parameters can be sent for each address object.
*
* #### Memo and Payment Instructions
*
* A custom memo can be sent with the `memo` parameter to override the site's default. Likewise, custom
* payment instructions can be sent with the `payment_instrucions` parameter.
*
* #### Status
*
* By default, invoices will be created with open status. Possible alternative is `draft`.
*
* @param subscriptionId The Chargify id of the subscription
* @param body
* @return Response from the API call
*/
async createInvoice(
subscriptionId: number,
body?: CreateInvoiceRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<InvoiceResponse>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
subscriptionId: [subscriptionId, number()],
body: [body, optional(createInvoiceRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/subscriptions/${mapped.subscriptionId}/invoices.json`;
req.throwOn(
422,
ErrorArrayMapResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceResponseSchema, requestOptions);
}
/**
* This endpoint allows for invoices to be programmatically delivered via email. This endpoint supports
* the delivery of both ad-hoc and automatically generated invoices. Additionally, this endpoint
* supports email delivery to direct recipients, carbon-copy (cc) recipients, and blind carbon-copy
* (bcc) recipients.
*
* Please note that if no recipient email addresses are specified in the request, then the
* subscription's default email configuration will be used. For example, if `recipient_emails` is left
* blank, then the invoice will be delivered to the subscription's customer email address.
*
* On success, a 204 no-content response will be returned. Please note that this does not indicate that
* email(s) have been delivered, but instead indicates that emails have been successfully queued for
* delivery. If _any_ invalid or malformed email address is found in the request body, the entire
* request will be rejected and a 422 response will be returned.
*
* @param uid The unique identifier for the invoice, this does not refer to
* the public facing invoice number.
* @param body
* @return Response from the API call
*/
async sendInvoice(
uid: string,
body?: SendInvoiceRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<void>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
uid: [uid, string()],
body: [body, optional(sendInvoiceRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/invoices/${mapped.uid}/deliveries.json`;
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.call(requestOptions);
}
/**
* Customer information may change after an invoice is issued which may lead to a mismatch between
* customer information that are present on an open invoice and actual customer information. This
* endpoint allows to preview these differences, if any.
*
* The endpoint doesn't accept a request body. Customer information differences are calculated on the
* application side.
*
* @param uid The unique identifier for the invoice, this does not refer to the public facing invoice
* number.
* @return Response from the API call
*/
async previewCustomerInformationChanges(
uid: string,
requestOptions?: RequestOptions
): Promise<ApiResponse<CustomerChangesPreviewResponse>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({ uid: [uid, string()] });
req.appendTemplatePath`/invoices/${mapped.uid}/customer_information/preview.json`;
req.throwOn(
404,
ErrorListResponseError,
true,
"Not Found:'{$response.body}'"
);
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(customerChangesPreviewResponseSchema, requestOptions);
}
/**
* This endpoint updates customer information on an open invoice and returns the updated invoice. If
* you would like to preview changes that will be applied, use the
* `/invoices/{uid}/customer_information/preview.json` endpoint before.
*
* The endpoint doesn't accept a request body. Customer information differences are calculated on the
* application side.
*
* @param uid The unique identifier for the invoice, this does not refer to the public facing invoice
* number.
* @return Response from the API call
*/
async updateCustomerInformation(
uid: string,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('PUT');
const mapped = req.prepareArgs({ uid: [uid, string()] });
req.appendTemplatePath`/invoices/${mapped.uid}/customer_information.json`;
req.throwOn(
404,
ErrorListResponseError,
true,
"Not Found:'{$response.body}'"
);
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
/**
* This endpoint allows you to issue an invoice that is in "pending" status. For example, you can issue
* an invoice that was created when allocating new quantity on a component and using "accrue charges"
* option.
*
* You cannot issue a pending child invoice that was created for a member subscription in a group.
*
* For Remittance subscriptions, the invoice will go into "open" status and payment won't be attempted.
* The value for `on_failed_payment` would be rejected if sent. Any prepayments or service credits that
* exist on subscription will be automatically applied. Additionally, if setting is on, an email will
* be sent for issued invoice.
*
* For Automatic subscriptions, prepayments and service credits will apply to the invoice and before
* payment is attempted. On successful payment, the invoice will go into "paid" status and email will
* be sent to the customer (if setting applies). When payment fails, the next event depends on the
* `on_failed_payment` value:
* - `leave_open_invoice` - prepayments and credits applied to invoice; invoice status set to "open";
* email sent to the customer for the issued invoice (if setting applies); payment failure recorded in
* the invoice history. This is the default option.
* - `rollback_to_pending` - prepayments and credits not applied; invoice remains in "pending" status;
* no email sent to the customer; payment failure recorded in the invoice history.
* - `initiate_dunning` - prepayments and credits applied to the invoice; invoice status set to "open";
* email sent to the customer for the issued invoice (if setting applies); payment failure recorded in
* the invoice history; subscription will most likely go into "past_due" or "canceled" state
* (depending upon net terms and dunning settings).
*
* @param uid The unique identifier for the invoice, this does not refer to
* the public facing invoice number.
* @param body
* @return Response from the API call
*/
async issueInvoice(
uid: string,
body?: IssueInvoiceRequest,
requestOptions?: RequestOptions
): Promise<ApiResponse<Invoice>> {
const req = this.createRequest('POST');
const mapped = req.prepareArgs({
uid: [uid, string()],
body: [body, optional(issueInvoiceRequestSchema)],
});
req.header('Content-Type', 'application/json');
req.json(mapped.body);
req.appendTemplatePath`/invoices/${mapped.uid}/issue.json`;
req.throwOn(404, ApiError, true, "Not Found:'{$response.body}'");
req.throwOn(
422,
ErrorListResponseError,
true,
"HTTP Response Not OK. Status code: {$statusCode}. Response: '{$response.body}'."
);
req.authenticate([{ basicAuth: true }]);
return req.callAsJson(invoiceSchema, requestOptions);
}
}