NAV Navbar
cURL .NET Java Go PHP Python Ruby

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 SettingsDevelopersAPI 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.