Introduction
Hello! Invoiced is an API for billing customers and getting paid.
Our API was designed to handle all of the billing needs for your business or application while making the integration process as painless as possible. Through the API we can help you seamlessly manage invoicing, payments, subscription billing, metered billing, estimates, pricing, and much more.
We designed the Invoiced API around REST principles.
Here's a few pages that might be helpful in addition to this API reference.
API Endpoint
All API calls must be made to https://api.invoiced.com
.
We also have a sandbox environment for testing available at https://api.sandbox.invoiced.com
.
JSON-only
All responses will be in JSON. Input data passed through the request body can be form-encoded or JSON-encoded. If using a JSON body, please specify the Content-Type
header as application/json
.
In the API dates are represented as UNIX timestamps. Each entity like customers or invoices has a unique integer ID.
PDFs
A few endpoints support returning a PDF response instead of JSON if you set the Accept
header to application/pdf
. For example, the retrieve invoice endpoint can return a PDF. The endpoints that support PDFs are notated in the documentation.
Client Libraries
We have client libraries available in several languages. If you don't see your language listed then please contact us and we would be happy to help.
Getting Help
If you need help using the API please message us at support@invoiced.com.
Authentication
The API uses HTTP Basic Authentication to authenticate users. A valid API key is required for all requests.
Obtaining an API Key
An API key can be obtained by signing in to invoiced.com, and then going to Settings → Developers → API Keys. Each business on Invoiced has its own set of API keys. We recommend creating a separate API key for each application that will be making calls on your behalf.
Usage
curl "https://api.invoiced.com/invoices" \
-u {YOUR_API_KEY}:
require "invoiced"
invoiced = Invoiced::Client.new("{YOUR_API_KEY}")
<?php
$invoiced = new Invoiced\Client("{YOUR_API_KEY}");
import invoiced
client = invoiced.Client("{YOUR_API_KEY}")
import com.invoiced.entity.Connection;
Connection invoiced = new Connection("{YOUR_API_KEY}",false);
import Invoiced;
var invoiced = new Connection("{YOUR_API_KEY}", Invoiced.Environment.production);
import (
"github.com/Invoiced/invoiced-go"
"github.com/Invoiced/invoiced-go/api"
)
client := api.New("{YOUR_API_KEY}", false)
The API key must be passed in through the username with the password left blank. The right sidebar has an example request with authorization
Sandbox API
curl "https://api.sandbox.invoiced.com/invoices" \
-u {YOUR_SANDBOX_API_KEY}:
require "invoiced"
invoiced = Invoiced::Client.new("{YOUR_SANDBOX_API_KEY}", true)
<?php
$invoiced = new Invoiced\Client("{YOUR_SANDBOX_API_KEY}", true);
import invoiced
client = invoiced.Client("{YOUR_SANDBOX_API_KEY}", True)
import com.invoiced.entity.Connection;
Connection invoiced = new Connection("{YOUR_API_KEY}",true);
import Invoiced;
var invoiced = new Connection("{YOUR_API_KEY}", Invoiced.Environment.sandbox);
import (
"github.com/Invoiced/invoiced-go"
"github.com/Invoiced/invoiced-go/api"
)
client := api.New("{YOUR_API_KEY}", true)
You can sign up for a sandbox account at sandbox.invoiced.com and request an API key there. The steps for requesting an API key are the same as production.
Errors
Each API call returns an HTTP status code that reflects the nature of the response. We have done our best to follow the HTTP status code conventions.
Any request that did not succeed will return a 4xx or 5xx error. The 4xx range means there was a problem with the request, like a missing parameter. The 5xx range means that something went wrong on our end.
The Invoiced API returns the following HTTP status codes:
200 OK -- Request succeeded
201 Created -- A resource was created
204 No Content -- Request succeeded but there is no response body
400 Bad Request -- Invalid request parameters
401 Unauthorized -- Incorrect or missing API key
403 Forbidden -- You do not have permission to view a resource or perform an action
404 Not Found -- The specified resource could not be found
429 Too Many Requests -- You're moving too fast! Slow down!
500 Internal Server Error -- There was a problem on our end
All error responses will contain an object with these attributes
Parameter | Description |
---|---|
type | Type of error, invalid_request or api |
message | Explanation of the error |
param | Available when a specific request parameter was responsible |
Pagination
Link: <https://api.invoiced.com/customers?page=3&per_page=10>; rel="self",
<https://api.invoiced.com/customers?page=1&per_page=10>; rel="first",
<https://api.invoiced.com/customers?page=2&per_page=10>; rel="previous",
<https://api.invoiced.com/customers?page=4&per_page=10>; rel="next",
<https://api.invoiced.com/customers?page=5&per_page=10>; rel="last"
All list operations will be paginated in similar fashion as the GitHub API. In most cases we will paginate requests returning more than 100 results. You can control pagination with the page
and per_page
parameters. Pages start at 1
and the first page will be returned if no page is specified.
When traversing the pages, we recommend using the Link
and X-Total-Count
headers. The Link header will return URLs that you can use to traverse the API without having to write your own. It's preferred to use the links from the API because it protects against future updates.
Versioning
Any future changes to the API will be versioned in order to maintain backwards compatibility with existing integrations.
Metadata
curl "https://api.invoiced.com/customers" \
-u {API_KEY}: \
-d name="Acme" \
-d metadata[icp_number]="1234567890" \
-d metadata[account_rep]="Jan"
invoiced.Customer.create(
:name => "Acme",
:metadata => {
:icp_number => "1234567890",
:account_rep => "Jan"
}
)
<?php
$invoiced->Customer->create([
'name' => "Acme",
'metadata' => [
'icp_number' => "1234567890",
'account_rep' => "Jan"
]
]);
client.Customer.create(
name="Acme",
metadata={
'icp_number': "1234567890",
'account_rep': "Jan"
}
)
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("icp_number", "1234567890");
params.put("account_rep","Jan");
Customer customer = invoiced.newCustomer();
customer.name = "Acme";
customer.metadata = params;
customer.create();
Dictionary<string, string> params = new Dictionary<string, string>();
params["icp_number"] = "1234567890";
params["account_rep"] = "Jan";
var customer = invoiced.NewCustomer();
customer.Name = "Acme";
customer.Metadata = params;
customer.Create();
customer, err := client.Customer.Create(&invoiced.CustomerRequest{
Name: invoiced.String("Acme"),
Metadata: map[string]interface{
"icp_number": "1234567890",
"account_rep": "Jan",
},
})
The above command returns JSON structured like this:
{
"ach_gateway": null,
"address1": null,
"address2": null,
"attention_to": null,
"autopay": true,
"autopay_delay_days": null,
"avalara_entity_use_code": null,
"avalara_exemption_number": null,
"cc_gateway": null,
"chase": true,
"chasing_cadence": null,
"city": null,
"country": "US",
"created_at": 1415222128,
"credit_hold": false,
"credit_limit": null,
"currency": null,
"email": "billing@acmecorp.com",
"id": 15444,
"language": null,
"metadata": {
"account_rep": "Jan",
"icp_number": "1234567890"
},
"name": "Acme",
"next_chase_step": null,
"notes": null,
"number": "CUST-0001",
"object": "customer",
"owner": null,
"parent_customer": null,
"payment_source": {
"brand": "Visa",
"exp_month": 2,
"exp_year": 20,
"funding": "credit",
"id": 850,
"last4": "4242",
"object": "card"
},
"payment_terms": null,
"phone": null,
"postal_code": null,
"sign_up_page": null,
"sign_up_url": null,
"state": null,
"statement_pdf_url": "https://dundermifflin.invoiced.com/statements/t3NmhUomra3g3ueSNnbtUgrr/pdf",
"tax_id": null,
"taxable": true,
"taxes": [],
"type": "company",
"updated_at": 1415222128
}
Most Invoiced objects have a metadata
attribute. This parameter allows you to store custom key-value data on supported objects.
There are many use cases for metadata. Any time you want to store custom, structured data on an object, like a Customer or Invoice, then metadata is a great fit. Metadata is only visible within the API and in the dashboard. Customers will not see this data unless you choose to display it with a custom field.
Our custom fields feature is backed by the metadata store. If you are using custom fields then be sure to use the ID of your custom field as the key for your metadata value in order to link it with the right custom field. Custom fields are not required in order to use metadata.
Metadata can include up to 10 keys per object. Each key can be up to 40 characters long and values may be up to 255 characters long.
Special Parameters
Expanding Relations
curl "https://api.invoiced.com/invoices/:id?expand=customer" \
-u {API_KEY}:
invoice = invoiced.Invoice.retrieve("{INVOICE_ID}", {
:expand => "customer"
})
<?php
$invoice = $invoiced->Invoice->retrieve("{INVOICE_ID}", [
'expand' => "customer"
]);
invoice = client.Invoice.retrieve("{INVOICE_ID}", {
'expand': "customer"
})
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("expand", "customer");
Invoice invoice = invoiced.newInvoice().retrieve("{INVOICE_ID}", params);
Dictionary<string, string> params = new Dictionary<string, string>();
params["expand"] = "customer";
var invoice = invoiced.NewInvoice().Retrieve("{INVOICE_ID}", params);
// Expands in the Go library are not currently supported.
Usually you need to request more than just an invoice. Often, you might want data about the associated customer. There is a built-in way to do this that saves extra API requests.
Certain relational properties can be expanded by passing in a comma-separated list of properties to expand through the expand
parameter. For example if you were requesting a payment and wanted to expand the associated customer and invoice objects you would set expand=customer,invoice
. This will replace the ID on the customer
and invoice
properties with expanded objects.
The expand
parameter works for any response that has relational properties.
Filter
Example retrieving a list of outstanding invoices for a customer:
curl "https://api.invoiced.com/invoices?filter%5Bpaid%5D=0&filter%5Bclosed%5D=0&filter%5Bcustomer%5D=1234" \
-u {API_KEY}:
invoices = invoiced.Invoice.list(
:filter => {
:paid => false,
:closed => false,
:customer => 1234
}
)
<?php
$invoices = $invoiced->Invoice->all([
'filter' => [
'paid' => false,
'closed' => false,
'customer' => 1234
]
]);
invoices = client.Invoice.list(
filter={
'paid': False,
'closed': False,
'customer': 1234
}
)
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("filter[paid]", false);
params.put("filter[closed]", false);
params.put("filter[customer]", 1234);
EntityList<Invoice> invoices = invoiced.newInvoice().listAll(filter);
Dictionary<string, string> params = new Dictionary<string, string>();
params["filter[paid]"] = false;
params["filter[closed]"] = false;
params["filter[customer]"] = 1234;
var invoices = invoiced.NewInvoice().ListAll(params);
filter := invoiced.NewFilter()
filter.Set("paid", false)
filter.Set("closed", false)
filter.Set("customer", 1234)
invoices, err := client.Invoice.ListAll(filter, nil)
The filter
parameter allows you to search entities based on an exact match. While it is not meant to replace a search API, the filter
parameter can be useful if you need to look up a customer by name or want to list all overdue invoices. It can be used on many of the list endpoints.
The filter
parameter is an object whose keys are the properties that should be matched.
Metadata Filter
Example retrieving customers with a matching
account-rep
metadata value:
curl "https://api.invoiced.com/customers?metadata%5Baccount-rep%5D=Jan" \
-u {API_KEY}:
customer = invoiced.Customer.list(
:metadata => {
'account-rep' => "Jan"
}
)
<?php
$customer = $invoiced->Customer->all([
'metadata' => [
'account-rep' => "Jan"
]
]);
customer = client.Customer.list(
metadata={
'account-rep': "Jan"
}
)
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("metadata[account-rep]", "Jan");
EntityList<Customer> customers = invoiced.newCustomer().listAll(params);
Dictionary<string, string> params = new Dictionary<string, string>();
params["metadata[account-rep]"] = "Jan";
var customers = invoiced.NewCustomer().ListAll(params);
filter := invoiced.NewMetadataFilter()
filter.Set("account-rep", "Jan")
customers, err := client.Customer.ListAll(filter, nil)
The metadata
parameter behaves in a similar fashion to the filter
parameter. It allows you to search entities that have an exactly matching metadata value for each constraint given. It can be used on any of the list endpoints for objects that support metadata.
The metadata
parameter is an object whose keys should exactly match the metadata of the objects returned. If an object does not have a metadata value for a given key then the object will not be included in the result set, with no error being thrown.