Recurly

Invoices API

An invoice record relates charges, credits, and transactions together. When a subscription is first created or renewed, Recurly will create an invoice for the new subscription charges and include any outstanding credits and charges. Once the invoice is created, it attempts to collect payment on the outstanding balance (if there are more charges than credits).

Table of Contents

List invoices

Returns a list of all invoices.

GET https://:subdomain.recurly.com/v2/invoices

Query Parameters

Parameter Default Description
state all The state of invoices to return: "open", "collected", "failed", or "past_due".
cursor Splits records across pages. Leave blank to return the first page. Follow the URI in the first page's Link header to fetch the next page.
per_page 50 Number of records to return per page, up to a maximum of 200.

Invoice States

open
Open, pending collection
collected
Collection completed successfully
failed
Failed to collect
past_due
Initial collection failed, still attempting collection

Please note: an invoice will only be in one state.

Example

Status: 200 OK
Content-Type: application/xml; charset=utf-8
X-Records: 123
Link: <https://your-subdomain.recurly.com/v2/invoices?cursor=1304958672>; rel="next"
ETag: "cd0faed6654f43768baf4282524f9782"
<?xml version="1.0" encoding="UTF-8"?>
<invoices type="array">
  <invoice href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d">
    <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
    <subscription href="https://your-subdomain.recurly.com/v2/subscriptions/17caaca1716f33572edc8146e0aaefde"/>
    <uuid>421f7b7d414e4c6792938e7c49d552e9</uuid>
    <state>open</state>
    <invoice_number type="integer">1005</invoice_number>
    <po_number nil="nil"></po_number>
    <vat_number nil="nil"></vat_number>
    <subtotal_in_cents type="integer">1200</subtotal_in_cents>
    <tax_in_cents type="integer">0</tax_in_cents>
    <total_in_cents type="integer">1200</total_in_cents>
    <currency>USD</currency>
    <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
    <closed_at nil="nil"></closed_at>
    <tax_type>usst</tax_type>
    <tax_rate type="float">0</tax_rate>
    <net_terms type="integer">0</net_terms>
    <collection_method>automatic</collection_method>
    <redemption href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d/redemption"/>
    <line_items type="array">
      <adjustment href="https://your-subdomain.recurly.com/v2/adjustments/05a4bbdeda2a47348185270021e6087b"/>
        <!-- Detail. -->
      </adjustment>
    </line_items>
    <transactions type="array">
    </transactions>
  </invoice>
  <!-- Continued... -->
</invoices>
$invoices = Recurly_InvoiceList::get();
foreach ($invoices as $invoice) {
  print "Invoice: $invoice\n";
}
The client library will automatically fetch the next page of the results. There may be a slight delay when fetching the next page.
Recurly::Invoice.find_each do |invoice|
  puts "Invoice: #{invoice.inspect}"
end
The client library will automatically fetch the next page of the results. There may be a slight delay when fetching the next page.
#client version <= 2.1.5
invoices = Invoice.all()
while invoices:
    for invoice in invoices:
        print 'Invoice: %s' % invoice
    try:
        invoices = invoices.next_page()
    except PageError:
        invoices = ()
# ...or...
past_due = Invoice.all_past_due()

#client version 2.1.6+
for invoice in Invoice.all():
    print 'Invoice: %s' % invoice

List an account's invoices

Returns a list of all the invoices.

GET https://:subdomain.recurly.com/v2/accounts/:account_code/invoices

Query Parameters

Parameter Default Description
cursor Splits records across pages. Leave blank to return the first page. Follow the URI in the first page's Link header to fetch the next page.
per_page 50 Number of records to return per page, up to a maximum of 200.

Example

Status: 200 OK
Content-Type: application/xml; charset=utf-8
X-Records: 92
Link: <https://your-subdomain.recurly.com/v2/accounts/1/invoices?cursor=1304958672>; rel="next"
ETag: "fab75c0e6cffe5bcf18442f8cbc4be3d"
<?xml version="1.0" encoding="UTF-8"?>
<invoices type="array">
  <invoice href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d">
    <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
    <subscription href="https://your-subdomain.recurly.com/v2/subscriptions/17caaca1716f33572edc8146e0aaefde"/>
    <uuid>421f7b7d414e4c6792938e7c49d552e9</uuid>
    <state>open</state>
    <invoice_number type="integer">1005</invoice_number>
    <po_number nil="nil"></po_number>
    <vat_number nil="nil"></vat_number>
    <subtotal_in_cents type="integer">1200</subtotal_in_cents>
    <tax_in_cents type="integer">0</tax_in_cents>
    <total_in_cents type="integer">1200</total_in_cents>
    <currency>USD</currency>
    <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
    <closed_at nil="nil"></closed_at>
    <tax_type>usst</tax_type>
    <tax_rate type="float">0</tax_rate>
    <net_terms type="integer">0</net_terms>
    <collection_method>automatic</collection_method>
    <redemption href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d/redemption"/>
    <line_items type="array">
      <adjustment href="https://your-subdomain.recurly.com/v2/adjustments/05a4bbdeda2a47348185270021e6087b"/>
        <!-- Detail. -->
      </adjustment>
    </line_items>
    <transactions type="array">
    </transactions>
  </invoice>
  <!-- Continued... -->
</invoices>
$invoices = Recurly_InvoiceList::getForAccount('account_code');
foreach ($invoices as $invoice) {
  print "Invoice: {$invoice}\n";
}
The client library will automatically fetch the next page of the results. There may be a slight delay when fetching the next page.
account = Recurly::Account.find('1')
account.invoices.find_each do |invoice|
  puts "Invoice: #{invoice.inspect}"
end
The client library will automatically fetch the next page of the results. There may be a slight delay when fetching the next page.
#client version <= 2.1.5
account = Account.get('1')
invoices = account.invoices()
while invoices:
    for invoice in invoices:
        print 'Invoice: %s' % invoice
    try:
        invoices = invoices.next_page()
    except PageError:
        invoices = ()

#client version 2.1.6+
account = Account.get('1')
for invoices in account.invoices():
    print 'Invoice: %s' % invoice

Lookup invoice details

Lookup an invoice to retrieve detailed information about its line items and payments.

GET https://:subdomain.recurly.com/v2/invoices/:invoice_number

Payments

Recurly returns an array of payments applied to an Invoice. At the moment, there is usually only one successful payment per invoice. The API only returns successful payments—it does not return failed payment attempts on an invoice nor does it return refunds on payments made to an invoice.

Example

Response

Status: 200 OK
Content-Type: application/xml; charset=utf-8
ETag: "66c8aa6c6b53123f99c43fe897e095ca"
<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d">
  <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
  <subscription href="https://your-subdomain.recurly.com/v2/subscriptions/17caaca1716f33572edc8146e0aaefde"/>
  <uuid>421f7b7d414e4c6792938e7c49d552e9</uuid>
  <state>open</state>
  <invoice_number type="integer">1402</invoice_number>
  <po_number nil="nil"></po_number>
  <vat_number nil="nil"></vat_number>
  <subtotal_in_cents type="integer">9900</subtotal_in_cents>
  <tax_in_cents type="integer">0</tax_in_cents>
  <total_in_cents type="integer">9900</total_in_cents>
  <currency>USD</currency>
  <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
  <closed_at nil="nil"></closed_at>
  <tax_type>usst</tax_type>
  <tax_rate type="float">0</tax_rate>
  <net_terms type="integer">0</net_terms>
  <collection_method>automatic</collection_method>
  <redemption href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d/redemption"/>
  <line_items type="array">
    <adjustment href="https://your-subdomain.recurly.com/v2/adjustments/05a4bbdeda2a47348185270021e6087b" type="charge"/>
      <!-- Detail. -->
    </adjustment>
  </line_items>
  <transactions type="array">
  </transactions>
</invoice>
try {
  $invoice = Recurly_Invoice::get('1005');
  print "Invoice: $invoice\n";
} catch (Recurly_NotFoundError $e) {
  print "Invoice not found.\n";
}
invoice = Recurly::Invoice.find('1005')
invoice = Invoice.get('1005')

Retrieve a PDF invoice

To retrieve a PDF invoice, modify the headers to request the Accept as "application/pdf".

GET https://:subdomain.recurly.com/v2/invoices/:invoice_number

Example

Request

Accept: application/pdf
try {
  $pdf = Recurly_Invoice::getInvoicePdf('invoice_number');
} catch (Recurly_NotFoundError $e) {
  print "Invoice not found.\n";
}
begin
  pdf = Recurly::Invoice.find(
    'invoice_number', :format => 'pdf'
  )
rescue Recurly::Resource::NotFound => e
  puts 'Invoice not found.'
end
with open('invoice.pdf', 'w') as invoice_file:
    invoice_file.write(recurly.Invoice.pdf('invoice_number'))

Post an invoice: invoice pending charges on an account

When you post one-time charges to an account, these will remain pending until they are invoiced. An account is automatically invoiced when the subscription renews. However, there are times when it is appropriate to invoice an account before the renewal. If the subscriber has a yearly subscription, you might want to collect the one-time charges well before the renewal.

POST https://:subdomain.recurly.com/v2/accounts/:account_code/invoices

Example

Response

Status: 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://your-subdomain.recurly.com/v2/invoices/421f7b7d414e4c6792938e7c49d552e9
<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://your-subdomain.recurly.com/v2/invoices/421f7b7d414e4c6792938e7c49d552e9">
  <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
  <subscription href="https://your-subdomain.recurly.com/v2/subscriptions/17caaca1716f33572edc8146e0aaefde"/>
  <uuid>421f7b7d414e4c6792938e7c49d552e9</uuid>
  <state>open</state>
  <invoice_number type="integer">1005</invoice_number>
  <po_number nil="nil"></po_number>
  <vat_number nil="nil"></vat_number>
  <subtotal_in_cents type="integer">1200</subtotal_in_cents>
  <tax_in_cents type="integer">0</tax_in_cents>
  <total_in_cents type="integer">1200</total_in_cents>
  <currency>USD</currency>
  <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
  <closed_at nil="nil"></closed_at>
  <tax_type>usst</tax_type>
  <tax_rate type="float">0</tax_rate>
  <net_terms type="integer">0</net_terms>
  <collection_method>automatic</collection_method>
  <redemption href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d/redemption"/>
  <line_items type="array">
    <adjustment href="https://your-subdomain.recurly.com/v2/adjustments/05a4bbdeda2a47348185270021e6087b" type="charge"/>
      <!-- Detail. -->
    </adjustment>
  </line_items>
  <transactions type="array">
  </transactions>
</invoice>

This API call will return the new invoice's details on success. If there are no pending charges, it will return an HTTP status code of 422 Unprocessable Entity.

$invoice = Recurly_Invoice::invoicePendingCharges('1');
account = Recurly::Account.find('1')
invoice = account.invoice!
account = Account.get('1')
invoice = account.invoice()

Mark an invoice as paid successfully

PUT https://:subdomain.recurly.com/v2/invoices/:invoice_number/mark_successful

Example

$invoice = Recurly_Invoice::get('e3f0a9e084a2468480d00ee61b090d4d');
$invoice->markSuccessful();
invoice = Recurly::Invoice.find('e3f0a9e084a2468480d00ee61b090d4d')
invoice.mark_successful
invoice = Invoice.get('e3f0a9e084a2468480d00ee61b090d4d')
invoice.mark_successful()
// TODO

Mark an invoice as failed collection

PUT https://:subdomain.recurly.com/v2/invoices/:invoice_number/mark_failed

Example

$invoice = Recurly_Invoice::get('e3f0a9e084a2468480d00ee61b090d4d');
$invoice->markFailed();
invoice = Recurly::Invoice.find('e3f0a9e084a2468480d00ee61b090d4d')
invoice.mark_failed
invoice = Invoice.get('e3f0a9e084a2468480d00ee61b090d4d')
invoice.mark_failed()
// TODO

Line item refunds

In enabled, allows specific invoice line items and/or quantities to be refunded.

POST https://:subdomain.recurly.com/v2/invoices/:invoice_number/refund

Refund Attributes

Parameter Description
uuid Unique transaction ID.Required
quantity Quantity of the line item to refund.Required
prorate Toggle to prorate the line item to refund. Set as true or false.

Example

Request

Accept: application/xml
Content-Type: application/xml; charset=utf-8
<invoice>
  <line_items>
    <adjustment>
      <uuid>626db120a84102b1809909071c701c60</uuid>
      <quantity>1</quantity>
      <prorate>false</prorate>
    </adjustment>
  </line_items>
</invoice>

Response

Status: 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d/refund
<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://your-subdomain.recurly.com/v2/invoices/e3f0a9e084a2468480d00ee61b090d4d">
  <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
  <uuid>421f7b7d414e4c6792938e7c49d552e9</uuid>
  <state>collected</state>
  <invoice_number type="integer">1010</invoice_number>
  <po_number nil="nil"></po_number>
  <vat_number nil="nil"></vat_number>
  <subtotal_in_cents type="integer">-200</subtotal_in_cents>
  <tax_in_cents type="integer">-18</tax_in_cents>
  <total_in_cents type="integer">-218</total_in_cents>
  <currency>USD</currency>
  <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
  <closed_at nil="nil"></closed_at>
  <tax_type>usst</tax_type>
  <tax_rate type="float">0.085</tax_rate>
  <net_terms type="integer">0</net_terms>
  <collection_method>automatic</collection_method>
  <line_items type="array">
    <adjustment href="https://your-subdomain.recurly.com/v2/adjustments/05a4bbdeda2a47348185270021e6087b" type="charge">
      <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
      <invoice href="https://your-subdomain.recurly.com/v2/invoices/1010"/>
      <uuid>2529f8eeec94a858bd8268461f8f1b30</uuid>
      <state>invoiced</state>
      <description>Refund for IP Addresses</description>
      <accounting_code></accounting_code>
      <product_code>ipaddresses</product_code>
      <origin>add_on</origin>
      <unit_amount_in_cents type="integer">200</unit_amount_in_cents>
      <quantity type="integer">-1</quantity>
      <quantity_remaining type="integer">9</quantity_remaining>
      <discount_in_cents type="integer">0</discount_in_cents>
      <tax_in_cents type="integer">-18</tax_in_cents>
      <total_in_cents type="integer">-218</total_in_cents>
      <currency>USD</currency>
      <tax_exempt type="boolean">false</tax_exempt>
      <start_date type="datetime">2011-08-25T12:00:00Z</start_date>
      <end_date nil="nil"></end_date>
      <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
    </adjustment>
  </line_items>
  <transactions type="array">
  </transactions>
</invoice>

Enter an offline payment for a manual invoice (beta)

Allows you to enter an offline payment for a manual invoice, such as a check or money order.

POST https://:subdomain.recurly.com/v2/invoices/invoice_number/transactions

Refund Attributes

Parameter Description
payment_method The method of payment. "credit_card", "paypal", "eft", "wire_transfer", "money_order", "check", or "other". Required
collected_at Date payment was collected.
amount_in_cents The amount paid in cents.
description Note for the manual payment. Max 50 characters.

Example

Request

Accept: application/xml
Content-Type: application/xml; charset=utf-8
<transaction>
 <payment_method>check</payment_method>
 <collected_at>2011-08-25T12:00:00Z</collected_at>
 <amount_in_cents>1000</amount_in_cents>
 <description>Paid with a check</description>
</transaction>

Response

Status: 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://your-subdomain.recurly.com/v2/transactions/a13acd8fe4294916b79aec87b7ea441f
<?xml version="1.0" encoding="UTF-8"?>
<transaction href="https://your-subdomain.recurly.com/v2/transactions/a13acd8fe4294916b79aec87b7ea441f">
  <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
  <invoice href="https://your-subdomain.recurly.com/v2/invoices/1108"/>
  <uuid>a13acd8fe4294916b79aec87b7ea441f</uuid>
  <action>purchase</action>
  <amount_in_cents type="integer">100</amount_in_cents>
  <tax_in_cents type="integer">0</tax_in_cents>
  <currency>USD</currency>
  <status>success</status>
  <payment_method>check</payment_method>
  <reference nil="nil"></reference>
  <source>transaction</source>
  <recurring type="boolean">false</recurring>
  <test type="boolean">true</test>
  <voidable type="boolean">true</voidable>
  <refundable type="boolean">false</refundable>
  <created_at type="datetime">2011-08-25T12:00:00Z</created_at>
  <details>
<account_code>1</account_code>
  <state>active</state>
  <username nil="nil"></username>
  <email>verena@example.com</email>
  <first_name>Verena</first_name>
  <last_name>Example</last_name>
  <company_name></company_name>
  <vat_number nil="nil"></vat_number>
  <tax_exempt type="boolean">false</tax_exempt>
  <address>
    <address1>123 Main St.</address1>
    <address2 nil="nil"></address2>
    <city>San Francisco</city>
    <state>CA</state>
    <zip>94105</zip>
    <country>US</country>
    <phone nil="nil"></phone>
  </address>
</account>
  </details>
  <a name="refund" href="https://your-subdomain.staging.recurly.com/v2/transactions/a13acd8fe4294916b79aec87b7ea441f" method="delete"/>
</transaction>
</invoice>