# The add-on object
This object represents an add-on, a one-time fee that can be applied on one-off invoices.
# Create an add-on
POST /add_ons
This endpoint is used to create an add-on that can be then attached to a one-off invoice.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/add_ons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"add_on": {
"name": "Setup Fee",
"code": "setup_fee",
"amount_cents": 50000,
"amount_currency": "USD",
"description": "Implementation fee for new customers.",
"tax_codes": ["french_reduced_vat"]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import AddOn
client = Client(api_key='__YOUR_API_KEY__')
add_on = AddOn(
name='Setup Fee',
code='setup_fee',
amount_cents=50000,
amount_currency='USD',
description='Implementation fee for new customers.',
tax_codes= ['french_standard_vat']
)
try:
client.add_ons.create(add_on)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
add_on = {
name: 'Setup Fee',
code: 'setup_fee',
description: 'Implementation fee for new customers.',
amount_cents: 50000,
amount_currency: 'USD',
tax_codes: ['french_standard_vat']
}
client.add_ons.create(add_on)
```
```js Javascript
const addOnObject = {
name: "Setup Fee",
code: "setup_fee",
description: "Implementation fee for new customers.",
amount_cents: 50000,
amount_currency: "USD",
tax_codes: ["french_standard_vat"],
};
await client.addOns.createAddOn({ addOn: addOnObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
addOnInput := &lago.AddOnInput{
Name: "Setup Fee",
Code: "setup_fee",
AmountCents: 50000,
AmountCurrency: lago.USD,
Description: "Implementation fee for new customers.",
}
addOn, err := lagoClient.AddOn().Create(addOnInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// addOn is *lago.AddOn
fmt.Println(addOn)
}
```
# Delete an add-on
DELETE /add_ons/{code}
This endpoint is used to delete an existing add-on.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/add_ons/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.add_ons.destroy('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.add_ons.destroy('code')
```
```js Javascript
await client.addOns.destroyAddOn('code')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
addOn, err := lagoClient.AddOn().Delete("__YOUR_ADDON_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// addOn is *lago.AddOn
fmt.Println(addOn)
}
```
# List all add-ons
GET /add_ons
This endpoint is used to list all existing add-ons.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/add_ons?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.add_ons.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.add_ons.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.addOns.findAllAddOns({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
addOnListInput := &lago.AddOnListInput{
PerPage: 1,
Page: 1,
}
addOnResult, err := lagoClient.AddOn().GetList(addOnListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// addOnResult is *lago.AddOnResult
fmt.Println(addOnResult)
}
```
# Retrieve an add-on
GET /add_ons/{code}
This endpoint is used to retrieve a specific add-on.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/add_ons/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.add_ons.find('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.add_ons.get('code')
```
```js Javascript
await client.addOns.findAddOn("code");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
addOn, err := lagoClient.AddOn().Get("__YOUR_ADDON_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// addOn is *lago.AddOn
fmt.Println(addOn)
}
```
# Update an add-on
PUT /add_ons/{code}
This endpoint is used to update an existing add-on.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/add_ons/:code" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"add_on": {
"name": "Setup Fee",
"code": "setup_fee",
"amount_cents": 50000,
"amount_currency": "USD",
"description": "Implementation fee for new customers."
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import AddOn
client = Client(api_key='__YOUR_API_KEY__')
update_params = AddOn(name='Setup Fee')
try:
client.add_ons.update(update_params, 'setup_fee')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
update_params = {name: 'Setup Fee'}
client.add_ons.update(update_params, 'setup_fee')
```
```js Javascript
await client.addOns.updateAddOn("code", {
add_on: { name: "Setup Fee", code: "setup_fee" },
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
addOnInput := &lago.AddOnInput{
Name: "Setup Fee",
Code: "setup_fee",
AmountCents: 50000,
AmountCurrency: lago.USD,
Description: "Implementation fee for new customers.",
}
addOn, err := lagoClient.AddOn().Update(addOnInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// addOn is *lago.AddOn
fmt.Println(addOn)
}
```
# Retrieve gross revenue
GET /analytics/gross_revenue
Gross revenue is the sum of monthly `finalized` invoice payments and fees paid in advance that are not invoiceable. This total is calculated after deducting taxes and discounts.
# Retrieve invoice collection
GET /analytics/invoice_collection
Represents a monthly aggregation, detailing both the total count and the cumulative amount of invoices that have been marked as `finalized`. This report sorts invoices categorically based on their `payment_status`.
# Retrieve invoiced usage
GET /analytics/invoiced_usage
Reports a monthly analysis focused on the revenue generated from all usage-based fees. It exclusively accounts for revenue that has been formally invoiced. Importantly, this report does not include revenue related to the usage in the current billing period, limiting its scope to previously invoiced amounts.
# Retrieve MRR (monthly recurring revenue)
GET /analytics/mrr
This endpoint is used to list MRR.
# Retrieve overdue balance
GET /analytics/overdue_balance
Overdue balance is the total amount associated with overdue invoices (invoices with pending or failed payments which are past their due dates).
# Create a billable metric
POST /billable_metrics
This endpoint creates a new billable metric representing a pricing component of your application.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "GB of storage used in my application",
"aggregation_type": "sum_agg",
"recurring": false,
"field_name": "gb",
"weighted_interval": "seconds",
"filters": [
{
"key": "region",
"values": ["us-east-1", "us-east-2", "eu-west-1"]
}
]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import BillableMetricFilter, BillableMetric
client = Client(api_key='__YOUR_API_KEY__')
filter = BillableMetricFilter(
key='region',
values=['us-east-1', 'us-east-2', 'eu-west-1']
)
billable_metric = BillableMetric(
name='Storage',
code='storage',
recurring=false,
description='GB of storage used in my application',
aggregation_type='sum_agg',
field_name='gb',
weighted_interval= 'seconds',
filters=[filter]
)
try:
client.billable_metrics.create(billable_metric)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.billable_metrics.create({
name: 'Storage',
code: 'storage',
description: 'GB of storage used in my application',
aggregation_type: 'sum_agg',
recurring: false,
field_name: 'gb',
weighted_interval: 'seconds',
filters: [
{
key: 'region',
values: %w[us-east-1 us-east-2 eu-west-1]
}
]
})
```
```js Javascript
await client.billableMetrics.createBillableMetric({
billable_metric: {
name: "Storage",
code: "storage",
aggregation_type: "sum_agg",
recurring: false,
field_name: "gb",
weighted_interval: "seconds",
filters: [
{
key: "region",
values: ["us-east-1", "us-east-2", "eu-west-1"],
}
]
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
bmInput := &lago.BillableMetricInput{
Name: "Storage",
Code: "storage",
Description: "GB of storage used in my application"
AggregationType: lago.SumAggregation,
FieldName: "gb",
WeightedInterval:"seconds",
Recurring: false,
Filters: [1]map[string]interface{}{
"key": "region",
"values": [3]string{"us-east-1", "us-east-2", "eu-west-1"},
},
}
billableMetric, err := lagoClient.BillableMetric().Create(bmInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// billableMetric is *lago.BillableMetric
fmt.Println(billableMetric)
}
```
# Delete a billable metric
DELETE /billable_metrics/{code}
This endpoint deletes an existing billable metric representing a pricing component of your application.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/billable_metrics/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.billable_metrics.destroy('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.billable_metrics.destroy('code')
```
```js Javascript
await client.billableMetrics.destroyBillableMetric('code')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
billableMetric, err := lagoClient.BillableMetric().Delete("__YOUR_BILLABLE_METRIC_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// billableMetric is *lago.BillableMetric
fmt.Println(billableMetric)
}
```
# List all billable metrics
GET /billable_metrics
This endpoint retrieves all existing billable metrics that represent pricing components of your application.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/billable_metrics?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.billable_metrics.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.billable_metrics.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.billableMetrics.findAllBillableMetrics({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
bmListInput := &lago.BillableMetricListInput{
PerPage: 10,
Page: 1,
}
billableMetricResult, err := lagoClient.BillableMetric().GetList(bmListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// billableMetric is *lago.BillableMetricResult
fmt.Println(billableMetricResult)
}
```
# List all billable metric groups
GET /billable_metrics/{code}/groups
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/billable_metrics/:code/groups?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.groups.find_all('billable_metric_code', {'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.groups.get_all('billable_metric_code', { per_page: 2, page: 3 })
```
```js Javascript
await client.billableMetrics.findAllBillableMetricGroups(
"billable_metric_code",
{ per_page: 2, page: 3 }
);
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
groupListInput := &lago.GroupListInput{
Code: "billable_metric_code",
PerPage: 10,
Page: 1,
}
groupResult, err := lagoClient.Group().GetList(groupListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// group is *lago.GroupResult
fmt.Println(groupResult)
}
```
# Retrieve a billable metric
GET /billable_metrics/{code}
This endpoint retrieves an existing billable metric that represents a pricing component of your application. The billable metric is identified by its unique code.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/billable_metrics/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.billable_metrics.find('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.billable_metrics.get('code')
```
```js Javascript
await client.billableMetrics.findBillableMetric('code');
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
billableMetric, err := lagoClient.BillableMetric().Get("__BILLABLE_METRIC_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// billableMetric is *lago.BillableMetric
fmt.Println(billableMetric)
}
```
# The billable metric object
This object represents a billable metric used to define how incoming events are aggregated in order to measure consumption.
# Update a billable metric
PUT /billable_metrics/{code}
This endpoint updates an existing billable metric representing a pricing component of your application.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/billable_metrics/:code" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "GB of storage used in my application",
"aggregation_type": "sum_agg",
"recurring": false,
"field_name": "gb",
"weighted_interval": "seconds",
"filters": [
{
"key": "provider",
"values": ["us-east-1", "us-east-2", "eu-west-1"]
}
]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import BillableMetricFilter, BillableMetric
client = Client(api_key='__YOUR_API_KEY__')
filter = BillableMetricFilter(
key='region',
values=['us-east-1', 'us-east-2', 'eu-west-1']
)
billable_metric = BillableMetric(
name='Storage',
code='storage',
description='GB of storage used in my application',
aggregation_type='sum_agg',
recurring=false,
field_name='gb',
weighted_interval= 'seconds',
filters=[filter]
)
try:
client.billable_metrics.update(billable_metric, 'code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.billable_metrics.update({
name: 'Storage',
code: 'storage',
description: 'GB of storage used in my application',
aggregation_type: 'sum_agg',
recurring: false,
field_name: 'gb',
weighted_interval: 'seconds',
filters: [
{
key: 'region',
values: %w[us-east-1 us-east-2 eu-west-1]
}
]
}, 'code')
```
```js Javascript
const newBillableMetricObject = {
name: "Storage",
code: "storage",
recurring: false,
aggregation_type: "sum_agg",
weighted_interval: "seconds",
field_name: "gb",
};
await client.billableMetrics.updateBillableMetric("code", {
billableMetric: newBillableMetricObject,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
bmInput := &lago.BillableMetricInput{
Name: "Storage",
Code: "storage",
Description: "GB of storage used in my application"
AggregationType: lago.SumAggregation,
FieldName: "gb",
Recurring: false,
WeightedInterval: "seconds",
Filters: [1]map[string]interface{}{
"key": "region",
"values": [3]string{"us-east-1", "us-east-2", "eu-west-1"},
},
}
billableMetric, err := lagoClient.BillableMetric().Update(bmInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// billableMetric is *lago.BillableMetric
fmt.Println(billableMetric)
}
```
# The applied coupon object
This object represents a coupon applied to a customer. It can override the initial values of a coupon.
```json The applied coupon object
{
"applied_coupon": {
"lago_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
"lago_coupon_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
"coupon_code": "startup_deal",
"coupon_name": "Startup Deal",
"lago_customer_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"status": "active",
"amount_cents": 2000,
"amount_cents_remaining": 50,
"amount_currency": "EUR",
"percentage_rate": "string",
"frequency": "recurring",
"frequency_duration": 3,
"frequency_duration_remaining": 1,
"expiration_at": "2022-04-29T08:59:51Z",
"created_at": "2022-04-29T08:59:51Z",
"terminated_at": "2022-04-29T08:59:51Z"
}
}
```
## Attributes
Unique identifier of the applied coupon, created by Lago.
Unique identifier of the coupon, created by Lago.
The name of the coupon.
Unique code used to identify the coupon.
The customer external unique identifier (provided by your own application)
Unique identifier of the customer, created by Lago.
The status of the coupon. Can be either `active` or `terminated`.
The amount of the coupon in cents. This field is required only for coupon with `fixed_amount` type.
The remaining amount in cents for a `fixed_amount` coupon with a frequency set to `once`.
This field indicates the remaining balance or value that can still be utilized from the coupon.
The currency of the coupon. This field is required only for coupon with `fixed_amount` type.
The expiration date and time of the coupon. This field is required only for coupons with `expiration` set to `time_limit`.
The expiration date and time should be specified in UTC format according to the ISO 8601 datetime standard.
It indicates the exact moment when the coupon will expire and is no longer valid.
The type of frequency for the coupon. It can have three possible values: `once`, `recurring`, or `forever`.
* If set to `once`, the coupon is applicable only for a single use.
* If set to `recurring`, the coupon can be used multiple times for recurring billing periods.
* If set to `forever`, the coupon has unlimited usage and can be applied indefinitely.
Specifies the number of billing periods to which the coupon applies. This field is required only for coupons
with a `recurring` frequency type
The remaining number of billing periods to which the coupon is applicable. This field determines the remaining
usage or availability of the coupon based on the remaining billing periods.
The percentage rate of the coupon. This field is required only for coupons with a `percentage` coupon type.
The date and time when the coupon was assigned to a customer. It is expressed in UTC format according to the ISO 8601 datetime standard.
This field indicates the specific moment when the coupon amount is fully utilized or when the coupon is removed from the customer's coupon list. It is expressed in UTC format according to the ISO 8601 datetime standard.
# Apply a coupon
POST /applied_coupons
This endpoint is used to apply a specific coupon to a customer, before or during a subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/applied_coupons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"applied_coupon": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"coupon_code": "startup_deal",
"amount_cents": 2500,
"amount_currency": "EUR",
"frequency": "recurring",
"frequency_duration": 3
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import AppliedCoupon
client = Client(api_key='__YOUR_API_KEY__')
applied_coupon = AppliedCoupon(
external_customer_id="5eb02857-a71e-4ea2-bcf9-57d8885990ba",
coupon_code="startup_deal",
amount_cents=2500,
amount_currency="EUR",
frequency="recurring",
frequency_duration=3
)
try:
client.applied_coupons.create(applied_coupon)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.applied_coupons.create(
external_customer_id: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
coupon_code: "startup_deal",
amount_cents: 2500,
amount_currency: "EUR",
frequency: "recurring",
frequency_duration: 3
)
```
```js Javascript
const appliedCouponObject = {
external_customer_id: "5eb02857-a71e-4ea2-bcf9-57d8885990ba",
coupon_code: "startup_deal",
amount_cents: 2500,
amount_currency: "EUR",
frequency: "recurring" as AppliedCouponObject["frequency"],
frequency_duration: 3,
};
await client.appliedCoupons.applyCoupon({
appliedCoupon: appliedCouponObject,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
applyCouponInput := &lago.ApplyCouponInput{
ExternalCustomerID: "5eb02857-a71e-4ea2-bcf9-57d8885990ba",
CouponCode: "startup_deal",
Frequency: lago.CouponFrequencyRecurring,
FrequencyDuration: 3
}
appliedCoupon, err := lagoClient.Coupon().ApplyToCustomer(applyCouponInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// appliedCoupon is *lago.AppliedCoupon
fmt.Println(appliedCoupon)
}
```
# The coupon object
This object represents a coupon used to applies discount on customer next invoices. This coupon can be applied to a customer with overriden values.
# Create a coupon
POST /coupons
This endpoint is used to create a coupon that can be then attached to a customer to create a discount.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/coupons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"coupon": {
"name": "Startup Deal",
"code": "startup_deal",
"amount_cents": 5000,
"amount_currency": "USD",
"coupon_type": "fixed_amount",
"reusable": true,
"frequency": "recurring",
"frequency_duration": 6,
"expiration": "time_limit",
"expiration_at": "2022-08-08T23:59:59Z",
"applies_to": {
"plan_codes": ["startup_plan"],
"billable_metric_codes": []
}
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Coupon
client = Client(api_key='__YOUR_API_KEY__')
coupon = Coupon(
name='Startup Deal',
code='startup_deal',
amount_cents=5000,
amount_currency='USD',
coupon_type='fixed_amount',
frequency='recurring',
frequency_duration=6,
reusable=True
expiration='time_limit',
expiration_at='2022-08-08T23:59:59Z',
applies_to=LimitationConfiguration(plan_codes=['startup_plan'])
)
try:
client.coupons.create(coupon)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
coupon = {
name: 'Startup Deal',
code: 'startup_deal',
expiration: 'time_limit',
expiration_at: '2022-08-08T23:59:59Z',
amount_cents: 5000,
amount_currency: 'USD',
coupon_type: 'fixed_amount',
reusable: true,
frequency: 'recurring',
frequency_duration: 6,
applies_to: {
plan_codes: ['startup_plan']
}
}
client.coupons.create(coupon)
```
```js Javascript
const couponObject = {
name: "Startup Deal",
code: "startup_deal",
expiration: "time_limit" as CouponObject["expiration"],
expiration_at: "2022-08-08T23:59:59Z",
amount_cents: 5000,
amount_currency: "USD",
coupon_type: "fixed_amount" as CouponObject["couponType"],
reusable: true,
frequency: "recurring" as CouponObject["frequency"],
frequency_duration: 6,
applies_to: {
plan_codes: ["startup_plan"],
},
};
await client.coupons.createCoupon({ coupon: couponObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
limitationInput := &lago.LimitationInput{
PlanCodes: []string{"startup_plan"}
}
couponInput := &lago.CouponInput{
Name: "Startup Deal",
Code: "startup_deal",
AmountCents: 5000,
AmountCurrency: lago.USD,
Reusable: true,
Expiration: lago.CouponExpirationTimeLimit,
ExpirationAt: "2022-08-08T23:59:59Z",
CouponType: lago.CouponTypeFixedAmount,
Frequency: lago.CouponFrequencyRecurring,
FrequencyDuration: 6,
AppliesTo limitationInput
}
coupon, err := lagoClient.Coupon().Create(couponInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// coupon is *lago.Coupon
fmt.Println(coupon)
}
```
# Delete a coupon
DELETE /coupons/{code}
This endpoint is used to delete a coupon.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/coupons/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.coupons.destroy('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.coupons.destroy('code')
```
```js Javascript
await client.coupons.destroyCoupon('code');
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
coupon, err := lagoClient.Coupon().Delete("__YOUR_COUPON_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// coupon is *lago.Coupon
fmt.Println(coupon)
}
```
# Delete an applied coupon
DELETE /customers/{external_customer_id}/applied_coupons/{applied_coupon_id}
This endpoint is used to delete a specific coupon that has been applied to a customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/customers/:external_customer_id/applied_coupons/:applied_coupon_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.applied_coupons.destroy('external_customer_id', 'applied_coupon_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.applied_coupons.destroy('external_customer_id', 'applied_coupon_id')
```
```js Javascript
await client.customers.deleteAppliedCoupon(
"external_customer_id",
"applied_coupon_id"
);
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
appliedCoupon, err := lagoClient.Coupon().AppliedCouponDelete('external_customer_id', 'applied_coupon_id')
if err != nil {
// Error is *lago.Error
panic(err)
}
// appliedCoupon is *lago.AppliedCoupon
fmt.Println(appliedCoupon)
}
```
# List all coupons
GET /coupons
This endpoint is used to list all existing coupons.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/coupons?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.coupons.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.coupons.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.coupons.findAllCoupons({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
couponListInput := &lago.CouponListInput{
PerPage: 1,
Page: 1,
}
couponResult, err := lagoClient.Coupon().GetList(couponListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// couponResult is *lago.CouponResult
fmt.Println(couponResult)
}
```
# List all applied coupons
GET /applied_coupons
This endpoint is used to list all applied coupons. You can filter by coupon status and by customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/applied_coupons?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.applied_coupons.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.applied_coupons.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.appliedCoupons.findAllAppliedCoupons({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
couponListInput := &lago.AppliedCouponListInput{
PerPage: 1,
Page: 1,
}
couponResult, err := lagoClient.AppliedCoupon().GetList(couponListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// couponResult is *lago.CouponResult
fmt.Println(couponResult)
}
```
# Retrieve a coupon
GET /coupons/{code}
This endpoint is used to retrieve a specific coupon.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/coupons/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.coupons.find('code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.coupons.get('code')
```
```js Javascript
await client.coupons.findCoupon('code')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
coupon, err := lagoClient.Coupon().Get("__YOUR_COUPON_CODE__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// coupon is *lago.Coupon
fmt.Println(coupon)
}
```
# Update a coupon
PUT /coupons/{code}
This endpoint is used to update a coupon that can be then attached to a customer to create a discount.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/coupons/:code" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"coupon": {
"name": "Startup Deal",
"code": "startup_deal",
"amount_cents": 5000,
"amount_currency": "USD",
"coupon_type": "fixed_amount",
"frequency": "recurring",
"frequency_duration": 6,
"reusable": true,
"expiration": "time_limit",
"expiration_at": "2022-08-08T23:59:59Z"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Coupon
client = Client(api_key='__YOUR_API_KEY__')
update_params = Coupon(name='new name')
try:
client.coupons.update(update_params, 'code')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
update_params = {name: 'new name'}
client.coupons.update(update_params, 'code_bm')
```
```js Javascript
await client.coupons.updateCoupon("code", { coupon: { name: "new name" } });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
couponInput := &lago.CouponInput{
Name: "Coupon",
Code: "coupon",
AmountCents: 1500,
AmountCurrency: lago.EUR,
Expiration: lago.CouponExpirationTimeLimit,
ExpirationAt: "2022-08-08T23:59:59Z",
}
coupon := lagoClient.Coupon().Update(couponInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// coupon is *lago.Coupon
fmt.Println(coupon)
}
```
# Create a credit note
POST /credit_notes
This endpoint creates a new credit note.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/credit_notes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"credit_note": {
"invoice_id": "__LAGO_INVOICE_ID__",
"reason": "duplicated_charge",
"credit_amount_cents": 10,
"refund_amount_cents": 5,
"items": [
{
"fee_id": "__LAGO_FEE_ID__",
"amount_cents": 10
},
{
"fee_id": "__LAGO_FEE_ID__",
"amount_cents": 5
}
]
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models.credit_note import Item, Items, CreditNote
client = Client(api_key='__YOUR_API_KEY__')
item1 = Item(
fee_id="__LAGO_FEE_ID__",
amount_cents=10
)
item2 = Item(
fee="__LAGO_FEE_ID__",
amount_cents=5,
)
credit_note = CreditNote(
lago_id="__LAGO_INVOICE_ID__",
reason="other",
credit_amount_cents=10,
refund_amount_cents=5,
items= Items(__root__=[item1, item2])
)
try:
client.credit_notes.create(credit_note)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
credit_note = {
invoice_id: '__LAGO_INVOICE_ID__',
reason: 'duplicated_charge',
credit_amount_cents: 10,
refund_amount_cents: 5,
items: [
{
fee_id: '__LAGO_FEE_ID__',
amount_cents: 10
},
{
fee_id: '__LAGO_FEE_ID__',
amount_cents: 5
}
]
}
client.credit_notes.create(credit_note)
```
```js Javascript
import { CreditNoteObject } from "lago-javascript-client";
const creditNoteObject = {
invoice_id: "__LAGO_INVOICE_ID__",
reason: "other" as CreditNoteObject["reason"],
credit_amount_cents: 10,
refund_amount_cents: 5,
items: [
{
fee_id: "__LAGO_FEE_ID__",
amount_cents: 10,
},
{
fee_id: "__LAGO_FEE_ID__",
amount_cents: 5,
},
],
};
await client.creditNotes.createCreditNote({ creditNote: creditNoteObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
creditNoteInput := &lago.CreditNoteInput{
LagoInvoiceID: "__LAGO_INVOICE_ID__",
Reason: lago.CreditNoteReasonDuplicatedCharge,
CreditAmountCents 10,
RefundAmountCents 5,
Items: []lago.CreditNoteItemInput{
{
LagoFeeID "__LAGO_FEE_ID__",
AmountCents 10,
},
{
LagoFeeID "__LAGO_FEE_ID__",
AmountCents 5,
},
},
}
creditNote, err := lagoClient.CreditNote().Create(creditNoteInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
fmt.Println(creditNote)
}
```
# The credit note object
This object represents a credit note, used to refund or credit back a customer for a fee or an invoice.
# Download a credit note
POST /credit_notes/{lago_id}/download
This endpoint downloads the PDF of an existing credit note.
```bash cURL
LAGO_URL="https://api.getlago.com"
CREDIT_NOTE_ID="__CREDIT_NOTE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/credit_notes/$CREDIT_NOTE_ID/download" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
invoice = None
try:
invoice = client.credit_notes.download('__CREDIT_NOTE_ID__')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.credit_notes.download('__CREDIT_NOTE_ID__')
```
```js Javascript
await client.creditNotes.downloadCreditNote('credit-note-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
credit_note, err := lagoClient.CreditNote().Download("__CREDIT_NOTE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// credit_note is *lago.CreditNote
fmt.Println(credit_note)
// If the credit note has to be generated, the response is empty
// And you will get a webhook `credit_note.generated`
}
```
# List all credit notes
GET /credit_notes
This endpoint list all existing credit notes.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/credit_notes?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.credit_notes.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.credit_notes.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.creditNotes.findAllCreditNotes({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
creditNoteListInput := &lago.CreditNoteListInput{
PerPage: 1,
Page: 1,
ExternalCustomerID: "cus_1234",
}
creditNoteResult, err := lagoClient.CreditNote().GetList(creditNoteListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// creditNoteResult is *lago.CreditNoteResult
fmt.Println(creditNoteResult)
}
```
# Retrieve a credit note
GET /credit_notes/{lago_id}
This endpoint retrieves an existing credit note.
```bash cURL
LAGO_URL="https://api.getlago.com"
CREDIT_NOTE_ID="__CREDIT_NOTE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/credit_notes/$CREDIT_NOTE_ID" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.credit_notes.find('__CREDIT_NOTE_ID__')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.credit_notes.get('__CREDIT_NOTE_ID__')
```
```js Javascript
await client.creditNotes.findCreditNote('credit-note-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
creditNote, err := lagoClient.CreditNotes().Get("__CREDIT_NOTE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// credit note is *lago.CreditNote
fmt.Println(creditNote)
}
```
# Update a credit note
PUT /credit_notes/{lago_id}
This endpoint updates an existing credit note.
# Void available credit
PUT /credit_notes/{lago_id}/void
This endpoint voids the available credit linked to a specific credit note.
```bash cURL
LAGO_URL="https://api.getlago.com"
CREDIT_NOTE_ID="__CREDIT_NOTE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/credit_notes/$CREDIT_NOTE_ID/void" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
try:
client.credit_notes.void("__CREDIT_NOTE_ID__")
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.credit_note.void('__CREDIT_NOTE_ID__')
```
```js Javascript
await client.creditNotes.voidCreditNote('credit-node-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
creditNote, err := lagoClient.CreditNote().Void("__CREDIT_NOTE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// creditNote is *lago.CreditNote
fmt.Println(creditNote)
}
```
# The customer usage object
This object represents the usage-based charges associated with one of your customers for a defined billing period. It allows you to monitor customer usage throughout the period.
# Retrieve current usage
GET /customers/{external_customer_id}/current_usage
Retrieve real-time customer usage data for the current open billing period.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_CUSTOMER_ID="__EXTERNAL_CUSTOMER_ID__"
EXTERNAL_SUBSCRIPTION_ID="__EXTERNAL_SUBSCRIPTION_ID__"
curl --location --request GET "$LAGO_URL/api/v1/customers/$EXTERNAL_CUSTOMER_ID/current_usage?external_subscription_id=$EXTERNAL_SUBSCRIPTION_ID" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
customer_usage = None
try:
customer_usage = client.customers.current_usage('external_customer_id', 'external_subscription_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
customer_usage = client.customer.current_usage(
'external_customer_id', 'external_subscription_id'
)
```
```js Javascript
await client.customers.findCustomerCurrentUsage(
"customer_external_id",
{ external_subscription_id: "external_subscription_id" }
);
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customerUsage, err := lagoClient.Customer().CurrentUsage("__YOUR_CUSTOMER_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customerUsage is *lago.CustomerUsage
fmt.Println(customerUsage)
}
```
# Retrieve past usage
GET /customers/{external_customer_id}/past_usage
Fetch historical customer usage data for closed billing periods.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_CUSTOMER_ID="__EXTERNAL_CUSTOMER_ID__"
EXTERNAL_SUBSCRIPTION_ID="__EXTERNAL_SUBSCRIPTION_ID__"
curl --location --request GET "$LAGO_URL/api/v1/customers/$EXTERNAL_CUSTOMER_ID/past_usage?external_subscription_id=$EXTERNAL_SUBSCRIPTION_ID" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
customer_usage = None
try:
customer_usage = client.customers.past_usage('external_customer_id', 'external_subscription_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
customer_usage = client.customer.past_usage(
'external_customer_id', 'external_subscription_id'
)
```
```js Javascript
await client.customers.findCustomerPastUsage(
"customer_external_id",
{ external_subscription_id: "external_subscription_id" }
);
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customerUsage, err := lagoClient.Customer().PastUsage("__YOUR_CUSTOMER_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customerUsage is *lago.CustomerUsage
fmt.Println(customerUsage)
}
```
# Create a customer
POST /customers
This endpoint creates a new customer.
This endpoint performs an upsert operation.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "USD",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
"provider_payment_methods": ["card", "sepa_debit", "us_bank_account", "bacs_debit", "link"]
},
"metadata": [
{
"key": "Purchase Order",
"value": "123456789",
"display_in_invoice": true
}
],
"tax_codes": ["french_standard_vat"]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Customer, CustomerBillingConfiguration
client = Client(api_key='__YOUR_API_KEY__')
metadata_object = Metadata(
display_in_invoice=True,
key='Purchase Order',
value='123456789'
)
customer = Customer(
external_id="5eb02857-a71e-4ea2-bcf9-57d8885990ba",
address_line1="5230 Penfield Ave",
address_line2=None,
city="Woodland Hills",
currency="USD",
country="US",
email="test@example.com",
legal_name="Coleman-Blair",
legal_number="49-008-2965",
tax_identification_number="EU123456789",
logo_url="http://hooli.com/logo.png",
name="Test Name",
phone="1-171-883-3711 x245",
state="CA",
timezone="Europe/Paris",
url="http://hooli.com",
zipcode="91364",
billing_configuration=CustomerBillingConfiguration(
invoice_grace_period=3,
payment_provider="stripe",
provider_customer_id="cus_12345",
sync=true,
sync_with_provider=true,
document_locale="fr"
),
metadata=MetadataList(__root__=[metadata_object])
)
try:
client.customers.create(customer)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.create(
external_id: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
address_line1: "5230 Penfield Ave",
address_line2: nil,
city: "Woodland Hills",
country: "US",
currency: "USD",
email: "dinesh@piedpiper.test",
legal_name: "Coleman-Blair",
legal_number: "49-008-2965",
tax_identification_number: "EU123456789",
logo_url: "http://hooli.com/logo.png",
name: "Gavin Belson",
phone: "1-171-883-3711 x245",
state: "CA",
timezone: "Europe/Paris",
url: "http://hooli.com",
zipcode: "91364",
billing_configuration: {
invoice_grace_period: 3,
payment_provider: "stripe",
provider_customer_id: "cus_12345",
sync: true,
sync_with_provider: true,
document_locale: "fr",
provider_payment_methods: ["card", "sepa_debit", "us_bank_account", "bacs_debit", "link"]
},
metadata: [
{
key: 'Purchase Order',
value: '123456789',
display_in_invoice: true
}
],
tax_codes: ["french_standard_vat"]
)
```
```js Javascript
import { BillingConfigurationCustomer } from "lago-javascript-client";
const customerObject = {
external_id: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
address_line1: "5230 Penfield Ave",
city: "Woodland Hills",
currency: "EUR",
country: "US",
email: "dinesh@piedpiper.test",
legal_name: "Coleman-Blair",
legal_number: "49-008-2965",
tax_identification_number: "EU123456789",
logo_url: "http://hooli.com/logo.png",
name: "Gavin Belson",
phone: "1-171-883-3711 x245",
state: "CA",
timezone: "Europe/Paris",
url: "http://hooli.com",
zipcode: "91364",
billing_configuration: {
invoice_grace_period: 3,
paymentProvider:
"stripe" as BillingConfigurationCustomer["paymentProvider"],
provider_customer_id: "cus_12345",
sync: true,
sync_with_provider: true,
document_locale: "fr"
},
metadata: [
{
key: "Purchase Order",
value: "123456789",
display_in_invoice: true,
},
],
};
await client.customers.createCustomer({ customer: customerObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customerInput := &lago.CustomerInput{
ExternalID: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
Name: "Gavin Belson",
Email: "dinesh@piedpiper.test",
AddressLine1: "5230 Penfield Ave",
AddressLine2: "",
City: "Woodland Hills",
Country: "US",
Currency: "USD",
State: "CA",
Zipcode: "75001",
LegalName: "Coleman-Blair",
LegalNumber: "49-008-2965",
TaxIdentificationNumber: "EU123456789",
Phone: "+330100000000",
Timezone: "Europe/Paris",
URL: "http://hooli.com",
BillingConfiguration: &CustomerBillingConfigurationInput{
InvoiceGracePeriod: 3,
PaymentProvider: lago.PaymentProviderStripe,
ProviderCustomerID: "cus_123456789",
SyncWithProvider: true,
DocumentLocale: "fr"
},
Metadata: [
&CustomerMetadataInput{
Key: "Purchase Order",
Value: "123456789",
DisplayInInvoice: true
}
]
}
customer, err := lagoClient.Customer().Create(customerInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// You can use the same input to update the customer
customer, err := lagoClient.Customer().Update(customerInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# Retrieve customer portal URL
GET /customers/{external_customer_id}/portal_url
Retrieves an embeddable link for displaying a customer portal.
This endpoint allows you to fetch the URL that can be embedded to provide customers access to a dedicated portal
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/customers/:external_id/portal_url" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.customers.portal_url('external_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.portal_url('external_id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customer, err := lagoClient.Customer().PortalUrl("__EXTERNAL_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# Delete a customer
DELETE /customers/{external_id}
This endpoint deletes an existing customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/customers/:external_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.customers.destroy('external_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.destroy('external_id')
```
```js Javascript
await client.customers.deleteCustomer('external_id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customer, err := lagoClient.Customer().Delete("external_id")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# List all customers
GET /customers
This endpoint retrieves all existing customers.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/customers?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.customers.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.customers.findAllCustomers({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customerListInput := &lago.CustomerListInput{
PerPage: 1,
Page: 1,
}
customerResult, err := lagoClient.Customer().GetList(customerListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// customerResult is *lago.CustomerResult
fmt.Println(customerResult)
}
```
# Retrieve a customer
GET /customers/{external_id}
This endpoint retrieves an existing customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/customers/:external_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.customers.find('external_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.get('external_id')
```
```js Javascript
await client.customers.findCustomer('external_id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customer, err := lagoClient.Customer().Get("__EXTERNAL_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# The customer object
This object represents a customer of your business. It lets you create or update a customer, but also track usage and create invoices for the same customer.
# Regenerate checkout URL
POST /customers/{external_customer_id}/checkout_url
This endpoint regenerates the Payment Provider Checkout URL of a Customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers/:external_id/checkout_url" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.customers.checkout_url('external_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.checkout_url('external_id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customer, err := lagoClient.Customer().CheckoutUrl("__EXTERNAL_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# Update a customer
POST /customers
This endpoint creates a new customer.
This endpoint performs an upsert operation.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "USD",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
"provider_payment_methods": ["card", "sepa_debit", "us_bank_account", "bacs_debit", "link"]
},
"metadata": [
{
"key": "Purchase Order",
"value": "123456789",
"display_in_invoice": true
}
],
"tax_codes": ["french_standard_vat"]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Customer, CustomerBillingConfiguration
client = Client(api_key='__YOUR_API_KEY__')
metadata_object = Metadata(
display_in_invoice=True,
key='Purchase Order',
value='123456789'
)
customer = Customer(
external_id="5eb02857-a71e-4ea2-bcf9-57d8885990ba",
address_line1="5230 Penfield Ave",
address_line2=None,
city="Woodland Hills",
currency="USD",
country="US",
email="test@example.com",
legal_name="Coleman-Blair",
legal_number="49-008-2965",
tax_identification_number="EU123456789",
logo_url="http://hooli.com/logo.png",
name="Test Name",
phone="1-171-883-3711 x245",
state="CA",
timezone="Europe/Paris",
url="http://hooli.com",
zipcode="91364",
billing_configuration=CustomerBillingConfiguration(
invoice_grace_period=3,
payment_provider="stripe",
provider_customer_id="cus_12345",
sync=true,
sync_with_provider=true,
document_locale="fr"
),
metadata=MetadataList(__root__=[metadata_object])
)
try:
client.customers.create(customer)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.customers.create(
external_id: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
address_line1: "5230 Penfield Ave",
address_line2: nil,
city: "Woodland Hills",
country: "US",
currency: "USD",
email: "dinesh@piedpiper.test",
legal_name: "Coleman-Blair",
legal_number: "49-008-2965",
tax_identification_number: "EU123456789",
logo_url: "http://hooli.com/logo.png",
name: "Gavin Belson",
phone: "1-171-883-3711 x245",
state: "CA",
timezone: "Europe/Paris",
url: "http://hooli.com",
zipcode: "91364",
billing_configuration: {
invoice_grace_period: 3,
payment_provider: "stripe",
provider_customer_id: "cus_12345",
sync: true,
sync_with_provider: true,
document_locale: "fr",
provider_payment_methods: ["card", "sepa_debit", "us_bank_account", "bacs_debit", "link"]
},
metadata: [
{
key: 'Purchas Order',
value: '123456789',
display_in_invoice: true
}
],
tax_codes: ["french_standard_vat"]
)
```
```js Node.js
import { BillingConfigurationCustomer } from "lago-javascript-client";
const customerObject = {
externalId: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
addressLine1: "5230 Penfield Ave",
city: "Woodland Hills",
currency: "EUR",
country: "US",
email: "dinesh@piedpiper.test",
legalName: "Coleman-Blair",
legalNumber: "49-008-2965",
taxIdentificationNumber: "EU123456789",
logoUrl: "http://hooli.com/logo.png",
name: "Gavin Belson",
phone: "1-171-883-3711 x245",
state: "CA",
timezone: "Europe/Paris",
url: "http://hooli.com",
zipcode: "91364",
billingConfiguration: {
invoiceGracePeriod: 3,
paymentProvider:
"stripe" as BillingConfigurationCustomer["paymentProvider"],
providerCustomerId: "cus_12345",
sync: true,
syncWithProvider: true,
documentLocale: "fr"
},
metadata: [
{
key: "Purchase Order",
value: "123456789",
displayInInvoice: true,
},
],
};
await client.customers.createCustomer({ customer: customerObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
customerInput := &lago.CustomerInput{
ExternalID: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
Name: "Gavin Belson",
Email: "dinesh@piedpiper.test",
AddressLine1: "5230 Penfield Ave",
AddressLine2: "",
City: "Woodland Hills",
Country: "US",
Currency: "USD",
State: "CA",
Zipcode: "75001",
LegalName: "Coleman-Blair",
LegalNumber: "49-008-2965",
TaxIdentificationNumber: "EU123456789",
Phone: "+330100000000",
Timezone: "Europe/Paris",
URL: "http://hooli.com",
BillingConfiguration: &CustomerBillingConfigurationInput{
InvoiceGracePeriod: 3,
PaymentProvider: lago.PaymentProviderStripe,
ProviderCustomerID: "cus_123456789",
SyncWithProvider: true,
DocumentLocale: "fr"
},
Metadata: [
&CustomerMetadataInput{
Key: "Purchase Order",
Value: "123456789",
DisplayInInvoice: true
}
]
}
customer, err := lagoClient.Customer().Create(customerInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// You can use the same input to update the customer
customer, err := lagoClient.Customer().Update(customerInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// customer is *lago.Customer
fmt.Println(customer)
}
```
# Batch usage events
POST /events/batch
This endpoint can be used to send a batch of usage records. Each request may include up to 100 events.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events/batch" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"events": [
{
"transaction_id": "__UNIQUE_ID__",
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"timestamp": $(date +%s),
"properties": {
"custom_field": 12
}
}
]
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import BatchEvent
client = Client(api_key='__YOUR_API_KEY__')
# Create a list of events
batch_event = BatchEvent(events=[
Event(
transaction_id="__UNIQUE_ID_1__",
external_subscription_id="__SUBSCRIPTION_ID_1__",
code="__BILLABLE_METRIC_CODE__",
timestamp=1650893379,
properties={"custom_field": "custom"}
),
Event(
transaction_id="__UNIQUE_ID_2__",
external_subscription_id="__SUBSCRIPTION_ID_2__",
code="__BILLABLE_METRIC_CODE__",
timestamp=1650893380,
properties={"custom_field": "custom"}
)
# Add more events as needed
])
try:
client.events.batch_create(batch_event)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
# Create an array of event hashes
events = [
{
transaction_id: "__UNIQUE_ID_1__",
external_subscription_id: "__SUBSCRIPTION_ID_1__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: Time.now.to_i,
properties: {
custom_field: "custom value 1"
}
},
{
transaction_id: "__UNIQUE_ID_2__",
external_subscription_id: "__SUBSCRIPTION_ID_2__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: Time.now.to_i,
properties: {
custom_field: "custom value 2"
}
}
# Add more events as needed
]
client.events.batch_create(events)
```
```js Javascript
const batchEvent = [
{
transaction_id: "__UNIQUE_TRANSACTION_ID_1__",
external_subscription_id: "__SUBSCRIPTION_ID_1__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: 1650893379,
properties: { customField: "custom1" },
},
{
transaction_id: "__UNIQUE_TRANSACTION_ID_2__",
external_subscription_id: "__SUBSCRIPTION_ID_2__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: 1650893380,
properties: { customField: "custom2" },
},
// Add more events as needed
];
await client.events.createBatchEvents({ events: batchEvent });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
ctx := context.Background()
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
event := lago.EventInput{
TransactionID: "__UNIQUE_TRANSACTION_ID__",
ExternalSubscriptionID: "__UNIQUE_SUBSCRIPTION_ID__",
Code: "__BILLABLE_METRIC_CODE__",
Timestamp: strconv.FormatInt(time.Now().Unix(), 10),
Properties: map[string]interface{}{
"nbusers": "12",
},
}
batchInput := make([]lago.EventInput, 1)
batchInput[0] = event
res, err := lagoClient.Event().Batch(ctx, &batchInput)
}
```
# Estimate an upcoming fee
POST /events/estimate_fees
Estimate the fees that would be created after reception of an event for a billable metric attached to one or multiple pay in advance charges.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events/estimate_fees" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"properties": {
"custom_field": 12,
}
}
}'
```
```python Python
from lago_python_client.models import Event
event = Event(
external_subscription_id="__YOUR_SUBSCRIPTION_ID__",
code="__BILLABLE_METRIC_CODE__",
)
client.events.estimate_fees(event)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.events.estimate_fees(
external_subscription_id: "__YOUR_SUBSCRIPTION_ID__",
code: "__BILLABLE_METRIC_CODE__",
properties: {
custom_field: 12,
}
)
```
```js Javascript
import { Client, getLagoError } from 'lago-javascript-client';
const lagoClient = Client('__YOUR_API_KEY__');
try {
const { data } = await lagoClient.events.eventEstimateFees(estimateEvent);
} catch (error) {
const lagoError = await getLagoError(error);
}
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
eventEstimateInput := &lago.EventEstimateFeesInput{
ExternalSubscriptionID: "__YOUR_SUBSCRIPTION_ID__",
Code: "__BILLABLE_METRIC_CODE__",
Properties: map[string]string{
"custom_field": "12",
},
}
err := lagoClient.Event().EstimateFees(eventEstimateInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
}
```
# The event object
Events represents usage measurement sent to lago application that will then be aggregated into invoice line items.
# Retrieve an event
GET /events/{transaction_id}
This endpoint is used for retrieving a specific usage measurement event that has been sent to a customer or a subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/events/:transaction_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.events.find("transaction_id")
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.events.get('transaction_id')
```
```js Javascript
await client.events.findEvent("__UNIQUE_TRANSACTION_ID__");
```
# List all events
GET /events
This endpoint is used for retrieving all events.
# Send usage event
POST /events
This endpoint is used for transmitting usage measurement events to either a designated customer or a specific subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "__UNIQUE_ID__",
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"timestamp": $(date +%s),
"properties": {
"custom_field": 12
}
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Event
client = Client(api_key='__YOUR_API_KEY__')
event = Event(
transaction_id="__UNIQUE_ID__",
external_subscription_id="__UNIQUE_ID__",
code="__BILLABLE_METRIC_CODE__",
timestamp=1650893379,
properties={"custom_field": "custom"}
)
try:
client.events.create(event)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.events.create(
transaction_id: "__UNIQUE_ID__",
external_subscription_id: "__SUBSCRIPTION_ID__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: Time.now.to_i,
properties: {
custom_field: 12
}
)
```
```js Javascript
await client.events.createEvent({
event: {
transaction_id: "__UNIQUE_TRANSACTION_ID__",
external_subscription_id: "__UNIQUE_SUBSCRIPTION_ID__",
code: "__BILLABLE_METRIC_CODE__",
timestamp: 1650893379,
properties: { customField: "custom" },
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
ctx := context.Background()
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
eventInput := &lago.EventInput{
TransactionID: "__UNIQUE_TRANSACTION_ID__",
ExternalSubscriptionID: "__UNIQUE_SUBSCRIPTION_ID__",
Code: "__BILLABLE_METRIC_CODE__",
Timestamp: strconv.FormatInt(time.Now().Unix(), 10),
Properties: map[string]interface{}{
"nbusers": "12",
},
}
res, err := lagoClient.Event().Create(ctx, eventInput)
if err != nil {
// err is *lago.Error
panic(err)
}
// res is *lago.Event
fmt.Println(*res)
}
```
# Delete a fee
DELETE /fees/{lago_id}
This endpoint is used for deleting a specific fee that has not yet been invoiced
# The fee object
This object represents a line item of an invoice, handling amount, billed units and item description.
# List all fees
GET /fees
This endpoint is used for retrieving all fees that has been issued.
```bash cURL
curl --location --request GET "$LAGO_URL/api/v1/fees?page=2&per_page=20&external_customer_id=hooli_1234" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client.fees.find_all({'per_page': 2, 'page': 1})
```
```ruby Ruby
require 'lago-ruby-client'
client.fees.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.fees.findAllFees({ per_page: 2, page: 3 });
```
```go Go
feeListInput := &lago.FeeListInput{
PerPage: 1,
Page: 1,
CreatedAtFrom: "2022-01-01T00:00:00Z",
CreatedAtTo: "2022-01-01T00:00:00Z",
}
feeResult, err := lagoClient.Fee().GetList(feeListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// feeResult is *lago.FeeResult
fmt.Println(feeResult)
```
# Retrieve a fee
GET /fees/{lago_id}
This endpoint is used for retrieving a specific fee that has been issued.
```bash cURL
LAGO_URL="https://api.getlago.com"
FEE_ID="__YOUR_FEE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/fees/$FEE_ID" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.fees.find('id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.fees.get('id')
```
```js Javascript
await client.fees.findFee('fee-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
fee, err := lagoClient.Fees().Get("id")
if err != nil {
// Error is *lago.Error
panic(err)
}
// credit note is *lago.Fee
fmt.Println(fee)
}
```
# Update a fee
PUT /fees/{lago_id}
This endpoint is used for updating a specific fee that has been issued.
```bash cURL
curl --location --request PUT "$LAGO_URL/api/v1/fees/1a901a90-1a90-1a90-1a90-1a901a901a90" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"fee": {
"payment_status": "succeeded"
}
}'
```
```python Python
from lago_python_client.models import Fee
fee_update = Fee(
payment_status="succeeded",
)
client.fees.update(fee_update, "1a901a90-1a90-1a90-1a90-1a901a901a90")
```
```ruby Ruby
require 'lago-ruby-client'
client.fees.update({
lago_id: "1a901a90-1a90-1a90-1a90-1a901a901a90",
payment_status: "succeeded",
})
```
```js Javascript
const feeObject = {
payment_status: "succeeded" as FeeObject["payment_status"],
};
await client.fees.updateFee("1a901a90-1a90-1a90-1a90-1a901a901a90", {
fee: feeObject,
});
```
```go Go
feeId, _ := uuid.Parse("1a901a90-1a90-1a90-1a90-1a901a901a90")
feeInput := &lago.FeeInput{
LagoID: invoiceId,
PaymentStatus: lago.FeePaymentStatusSucceeded,
}
fee, err := lagoClient.Fee().Update(feeInput)
if err != nil {
panic(err)
}
// fee is *lago.Fee
fmt.Println(fee)
}
```
# Getting started
Lago API allows your application to push customer information and metrics (events) from your application to the billing application.
To integrate it into your application, you can use the JSON HTTP API or one of
the Lago libraries (depending on your programing language or framework).
You must retrieve your API key from your account.
## Configuration[](#configuration "Direct link to heading")
```shell
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/..." \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '...'
```
**Install package with pip**
```bash
pip install lago-python-client
```
**Usage**
```python
from lago_python_client import Client
# By default, this connects to Lago's hosted servers in the US region.
client = Client(api_key='__YOUR_API_KEY__')
# If you are self-hosting Lago or using a different server region,
# specify the API URL to connect to the correct instance.
# Replace '__YOUR_LAGO_URL__' with the appropriate URL for your Lago server.
# Example: 'https://api.eu.getlago.com/api/v1' for the EU region.
# client = Client(api_key='__YOUR_API_KEY__', api_url='__YOUR_LAGO_URL__')
```
**Add the gem in your Gemfile**
```bash
bundle add lago-ruby-client
```
Or if bundler is not being used to manage dependencies, install the gem by
executing:
```bash
$ gem install lago-ruby-client
```
**Usage**
```ruby
require 'lago-ruby-client'
# By default, this will connect to the US region of Lago's hosted servers.
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
# If you are self-hosting Lago or using Lago in a different region (e.g., Europe),
# you need to specify the API URL to connect to the correct server.
# For example, you can provide the base URL for your specific Lago instance.
# This example shows how to specify a different Lago server when needed.
#
# Replace '__YOUR_LAGO_URL__' with the appropriate URL of your Lago instance.
# Example: 'https://api.eu.getlago.com/api/v1' for the EU region.
#
# client = Lago::Api::Client.new(
# api_key: '__YOUR_API_KEY__',
# api_url: '__YOUR_LAGO_URL__'
# )
```
**Install package with npm**
```bash
npm install lago-javascript-client
```
**Usage**
```js
import { Client } from 'lago-javascript-client'
// By default, this will connect to Lago's hosted servers in the US region.
const client = Client('__YOUR_API_KEY__')
// If you are self-hosting Lago or using a different region (e.g., EU),
// you need to specify the base URL to connect to the correct Lago instance.
// Replace '__YOUR_LAGO_URL__' with the appropriate URL for your Lago instance.
// Example: 'https://api.eu.getlago.com/api/v1' for the EU region.
// const client = Client('__YOUR_API_KEY__', { baseUrl: '__YOUR_LAGO_URL__' })
```
**Install package**
```bash
go get github.com/getlago/lago-go-client@v1
```
**Usage**
```go
import "github.com/getlago/lago-go-client"
func main() {
// By default, this will connect to Lago's hosted servers in the US region.
lagoClient := lago.New().SetApiKey("__YOU_API_KEY__")
// If you are self-hosting Lago or using a different region (e.g., EU),
// you need to specify the base URL to connect to the correct Lago instance.
// Replace '__YOUR_LAGO_URL__' with the appropriate URL for your Lago instance.
// Example: 'https://api.eu.getlago.com/api/v1' for the EU region.
// lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__").SetBaseURL("__YOUR_LAGO_URL__")
}
```
# Create a one-off invoice
POST /invoices
This endpoint is used for issuing a one-off invoice.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/invoices" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"invoice": {
"external_customer_id": "hooli_1234",
"currency": "USD",
"fees": [
{
"add_on_code": "setup_fee",
"units": 2.5,
"unit_amount_cents": 1200,
"description": "This is a description.",
"tax_codes": ["french_standard_vat]
}
]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import InvoiceFee, OneOffInvoice, InvoiceFeesList
client = Client(api_key='__YOUR_API_KEY__')
fee_object = InvoiceFee(
add_on_code='setup_fee',
units=2.5,
unit_amount_cents=1200,
description='This is a description.'
)
invoice_create = OneOffInvoice(
external_customer_id="hooli_1234",
currency="USD",
fees=InvoiceFeesList(__root__=[fee_object])
)
try:
client.invoices.create(invoice_create)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.create({
external_customer_id: "hooli_1234",
currency: 'USD',
fees: [
{
add_on_code: 'setup_fee',
units: 2.5,
unit_amount_cents: 1200,
description: 'This is a description.'
}
]
})
```
```js Javascript
const invoiceObject = {
external_customer_id: "hooli_1234",
currency: "USD",
fees: [
{
add_on_code: "setup_fee",
description: "This is a description.",
units: 2.5,
unit_amount_cents: 1200,
},
],
};
await client.invoices.createInvoice({
invoice: invoiceObject,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoiceInput := &lago.OneOffInput{
ExternalCustomerId: custID,
currency: "USD",
Fees: [
&InvoiceFeesInput{
AddOnCode: "setup_fee",
Description: "This is a description.",
Units: 2.5,
UnitAmountCents: 1200
}
]
}
invoice, err := lagoClient.Invoice().Create(invoiceInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
}
```
# Download an invoice
POST /invoices/{lago_id}/download
This endpoint is used for downloading a specific invoice PDF document.
```bash cURL
LAGO_URL="https://api.getlago.com"
INVOICE_ID="__YOUR_INVOICE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/invoices/$INVOICE_ID/download" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
invoice = None
try:
invoice = client.invoices.download('__YOUR_INVOICE_ID__') # Invoice ID
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.download('__YOUR_INVOICE_ID__') // Invoice ID
```
```js Javascript
await client.invoices.downloadInvoice('invoice-id');
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoice, err := lagoClient.Invoice().Download("__YOUR_INVOICE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
// If the invoice has to be generated, the response is empty
// And you will get a webhook `invoice.generated`
}
```
# Finalize an invoice
PUT /invoices/{lago_id}/finalize
This endpoint is used for finalizing a draft invoice.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/invoices/:lago_invoice_id/finalize" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.invoices.finalize('__INVOICE_ID__') # Invoice ID
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.finalize('__INVOICE_ID__') // Invoice ID
```
```js Javascript
await client.invoices.finalizeInvoice("invoice-id");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoice, err := lagoClient.Invoice().Finalize("__YOUR_INVOICE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
}
```
# List all invoices
GET /invoices
This endpoint is used for retrieving all invoices.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/invoices?page=2&per_page=20&external_customer_id=hooli_1234" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.invoices.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.invoices.findAllInvoices({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoiceListInput := &lago.InvoiceListInput{
PerPage: 1,
Page: 1,
IssuingDateFrom: "2022-01-01",
IssuingDateTo: "2022-01-01",
}
invoiceResult, err := lagoClient.Invoice().GetList(invoiceListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoiceResult is *lago.InvoiceResult
fmt.Println(invoiceResult)
}
```
# Retrieve an invoice
GET /invoices/{lago_id}
This endpoint is used for retrieving a specific invoice that has been issued.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/invoices/:lago_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.invoices.find('lago_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.get('lago_id')
```
```js Javascript
await client.invoices.findInvoice('lago-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoice, err := lagoClient.Invoice().Get("lago_id")
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
}
```
# The invoice object
This object represents an invoice generated by Lago for a specific customer. This invoice summarizes the fees generated by a subscription, usage-based charges, prepaid credit purchases, or one-off invoices.
# Generate a payment URL
POST /invoices/{lago_id}/payment_url
This endpoint generates a checkout link for a specific invoice.
# Refresh an invoice
PUT /invoices/{lago_id}/refresh
This endpoint is used for refreshing a draft invoice.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/invoices/:lago_invoice_id/refresh" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.invoices.refresh('__INVOICE_ID__') # Invoice ID
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.refresh('__INVOICE_ID__') // Invoice ID
```
```js Javascript
await client.invoices.refreshInvoice('invoice-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoice, err := lagoClient.Invoice().Refresh("__INVOICE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
}
```
# Retry an invoice payment
POST /invoices/{lago_id}/retry_payment
This endpoint resends an invoice for collection and retry a payment.
```bash cURL
LAGO_URL="https://api.getlago.com"
INVOICE_ID="__INVOICE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/invoices/$INVOICE_ID/retry_payment" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
invoice = None
try:
invoice = client.invoices.retry_payment('__INVOICE_ID__') # Invoice ID
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.retry_payment('__INVOICE_ID__') // Invoice ID
```
```js Javascript
await client.invoices.retryPayment("invoice-id");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoice, err := lagoClient.Invoice().RetryPayment("__INVOICE_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
// If the invoice has to be generated, the response is empty
// And you will get a webhook `invoice.generated`
}
```
# Retry an invoice finalization
POST /invoices/{lago_id}/retry
This endpoint is used for retrying to generate a failed invoice.
# Update an invoice
PUT /invoices/{lago_id}
This endpoint is used for updating an existing invoice.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/invoices/:lago_id" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"invoice": {
"payment_status": "succeeded",
"metadata": [
{
"id": "__METADATA_ID__",
"key": "digital_ref_id",
"value": "INV-0123456-98765"
}
]
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import InvoicePaymentStatusChange
client = Client(api_key='__YOUR_API_KEY__')
metadata_object = InvoiceMetadata(
key='key',
value='value'
)
invoice_update = Invoice(
payment_status="succeeded",
metadata=InvoiceMetadataList(__root__=[metadata_object])
)
try:
client.invoices.update(invoice_update, "__INVOICE_ID__")
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
# Deprecated
payment_status_change = InvoicePaymentStatusChange(
payment_status="succeeded"
)
try:
client.invoices.update(payment_status_change, "__INVOICE_ID__")
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.invoices.update({
lago_id: "__INVOICE_ID__",
payment_status: "succeeded",
metadata: [
{
key: 'key',
value: 'value'
}
]
})
```
```js Javascript
const invoiceObject = {
payment_status: "succeeded" as InvoiceObject["payment_status"],
metadata: [
{
key: "key",
value: "value",
},
],
};
await client.invoices.updateInvoice("invoice-id", {
invoice: invoiceObject,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
invoiceId, _ := uuid.Parse("__YOUR_INVOICE_ID__")
invoiceInput := &lago.InvoiceInput{
LagoID: invoiceId,
PaymentStatus: lago.InvoicePaymentStatusSucceeded,
Metadata: [
&InvoiceMetadataInput{
Key: "Key",
Value: "Value"
}
]
}
invoice, err := lagoClient.Invoice().Update(invoiceInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// invoice is *lago.Invoice
fmt.Println(invoice)
}
```
# Void an invoice
POST /invoices/{lago_id}/void
This endpoint is used for voiding an invoice. You can void an invoice only when it's in a `finalized` status, and the payment status is not `succeeded`.
# The organization object
This object represents your organization. You can define all invoicing details and settings within it.
# Update your organization
PUT /organizations
This endpoint is used to update your own organization's settings.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"webhook_url": "https://webhook.brex.com",
"country": "US",
"address_line1": "100 Brex Street",
"address_line2": null,
"state": "NYC",
"zipcode": "10000",
"email": "brex@brex.com",
"city": "New York",
"legal_name": null,
"legal_number": null,
"net_payment_term": 30,
"tax_identification_number": "US123456789",
"timezone": "America/New_York",
"default_currency": "USD",
"document_numbering": "per_customer",
"document_number_prefix": "LAGO-INV",
"email_settings": [
"invoice.finalized",
"credit_note.created"
],
"billing_configuration": {
"invoice_footer": "This is my customer footer",
"invoice_grace_period": 3,
"document_locale": "en",
"vat_rate": 12.5
}
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Organization, OrganizationBillingConfiguration
client = Client(api_key='__YOUR_API_KEY__')
params = Organization(
timezone="America/New_York",
webhook_url="https://webhook.brex.com",
email_settings=["invoice.finalized"],
tax_identification_number="US123456789",
default_currency="USD",
document_numbering= "per_customer",
document_number_prefix= "LAGO-INV",
billing_configuration=OrganizationBillingConfiguration(
invoice_footer="This is my customer footer",
invoice_grace_period=3,
document_locale="en",
vat_rate=12.5
)
)
try:
client.organizations.update(params)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
update_params = {
timezone: 'America/New_York',
webhook_url: 'https://webhook.brex.com',
email_settings: ['invoice.finalized'],
tax_identification_number: "US123456789",
default_currency: "USD",
document_numbering: 'per_customer',
document_number_prefix: 'LAGO-INV',
billing_configuration: {
invoice_footer="This is my customer footer",
invoice_grace_period=3,
document_locale: "en",
vat_rate: 12.5
}
}
client.organizations.update(update_params)
```
```js Javascript
await client.organizations.updateOrganization({
organization: {
timezone: "America/New_York",
webhook_url: "https://webhook.brex.com",
email_settings: ["invoice.finalized"],
tax_identification_number: "US123456789",
default_currency: "USD",
document_numbering: "per_customer",
document_number_prefix: "LAGO-INV",
billing_configuration: {
invoice_footer: "This is my customer footer",
invoice_grace_period: 3,
document_locale: "en",
vat_rate: 12.5,
},
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
organizationInput := &lago.OrganizationInput{
LegalName: "Legal Name",
Timezone: "America/New_York",
EmailSettings: ["invoice.finalized"],
TaxIdentificationNumber: "US123456789",
DefaultCurrency: "USD",
BillingConfiguration: &OrganizationBillingConfigurationInput{
InvoiceFooter: "This is my customer foote",
InvoiceGracePeriod: 3,
DocumentLocale: "en",
VatRate: 12.5,
}
}
organization, err := lagoClient.Organization().Update(organizationInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// organization is *lago.Organization
fmt.Println(organization)
}
```
# Create a payment request
POST /payment_requests
This endpoint is used to create a payment request to collect payments of overdue invoices of a given customer
# List all payment requests
GET /payment_requests
This endpoint is used to list all existing payment requests.
# The payment request object
This object represents payment request of a group of overdue invoices for which a payment intent can be created, to settle the overdue balance.
# Create a plan
POST /plans
This endpoint creates a plan with subscription and usage-based charges. It supports flexible billing cadence (in-advance or in-arrears) and allows for both recurring and metered charges.
# Delete a plan
DELETE /plans/{code}
This endpoint deletes a specific plan. Note that this plan could be associated with active subscriptions.
# List all plans
GET /plans
This endpoint retrieves all existing plans.
# Retrieve a plan
GET /plans/{code}
This endpoint retrieves a specific plan.
# The plan object
This object represents a plan. This plan can then be assigned to a customer.
# Update a plan
PUT /plans/{code}
This endpoint updates a specific plan with subscription and usage-based charges. It supports flexible billing cadence (in-advance or in-arrears) and allows for both recurring and metered charges.
# Currencies
List of accepted currencies (ISO 4217).
| Code | Currency name |
| ----- | ----------------------------------------- |
| `AED` | `United Arab Emirates Dirham` |
| `AFN` | `Afghan Afghani` |
| `ALL` | `Albanian Lek` |
| `AMD` | `Armenian Dram` |
| `ANG` | `Netherlands Antillean Gulden` |
| `AOA` | `Angolan Kwanza` |
| `ARS` | `Argentine Peso` |
| `AUD` | `Australian Dollar` |
| `AWG` | `Aruban Florin` |
| `AZN` | `Azerbaijani Manat` |
| `BAM` | `Bosnia and Herzegovina Convertible Mark` |
| `BBD` | `Barbadian Dollar` |
| `BDT` | `Bangladeshi Taka` |
| `BGN` | `Bulgarian Lev` |
| `BIF` | `Burundian Franc` |
| `BMD` | `Bermudian Dollar` |
| `BND` | `Brunei Dollar` |
| `BOB` | `Bolivian Boliviano` |
| `BRL` | `Brazilian Real` |
| `BSD` | `Bahamian Dollar` |
| `BWP` | `Botswana Pula` |
| `BYN` | `Belarusian Ruble` |
| `BZD` | `Belize Dollar` |
| `CAD` | `Canadian Dollar` |
| `CDF` | `Congolese Franc` |
| `CHF` | `Swiss Franc` |
| `CLF` | `Unidad de Fomento` |
| `CLP` | `Chilean Peso` |
| `CNY` | `Chinese Renminbi Yuan` |
| `COP` | `Colombian Peso` |
| `CRC` | `Costa Rican Colón` |
| `CVE` | `Cape Verdean Escudo` |
| `CZK` | `Czech Koruna` |
| `DJF` | `Djiboutian Franc` |
| `DKK` | `Danish Krone` |
| `DOP` | `Dominican Peso` |
| `DZD` | `Algerian Dinar` |
| `EGP` | `Egyptian Pound` |
| `ETB` | `Ethiopian Birr` |
| `EUR` | `Euro` |
| `FJD` | `Fijian Dollar` |
| `FKP` | `Falkland Pound` |
| `GBP` | `British Pound` |
| `GEL` | `Georgian Lari` |
| `GIP` | `Gibraltar Pound` |
| `GMD` | `Gambian Dalasi` |
| `GNF` | `Guinean Franc` |
| `GTQ` | `Guatemalan Quetzal` |
| `GYD` | `Guyanese Dollar` |
| `HKD` | `Hong Kong Dollar` |
| `HNL` | `Honduran Lempira` |
| `HRK` | `Croatian Kuna` |
| `HTG` | `Haitian Gourde` |
| `HUF` | `Hungarian Forint` |
| `IDR` | `Indonesian Rupiah` |
| `ILS` | `Israeli New Sheqel` |
| `INR` | `Indian Rupee` |
| `ISK` | `Icelandic Króna` |
| `JMD` | `Jamaican Dollar` |
| `JPY` | `Japanese Yen` |
| `KES` | `Kenyan Shilling` |
| `KGS` | `Kyrgyzstani Som` |
| `KHR` | `Cambodian Riel` |
| `KMF` | `Comorian Franc` |
| `KRW` | `South Korean Won` |
| `KYD` | `Cayman Islands Dollar` |
| `KZT` | `Kazakhstani Tenge` |
| `LAK` | `Lao Kip` |
| `LBP` | `Lebanese Pound` |
| `LKR` | `Sri Lankan Rupee` |
| `LRD` | `Liberian Dollar` |
| `LSL` | `Lesotho Loti` |
| `MAD` | `Moroccan Dirham` |
| `MDL` | `Moldovan Leu` |
| `MGA` | `Malagasy Ariary` |
| `MKD` | `Macedonian Denar` |
| `MMK` | `Myanmar Kyat` |
| `MNT` | `Mongolian Tögrög` |
| `MOP` | `Macanese Pataca` |
| `MRO` | `Mauritanian Ouguiya` |
| `MUR` | `Mauritian Rupee` |
| `MVR` | `Maldivian Rufiyaa` |
| `MWK` | `Malawian Kwacha` |
| `MXN` | `Mexican Peso` |
| `MYR` | `Malaysian Ringgit` |
| `MZN` | `Mozambican Metical` |
| `NAD` | `Namibian Dollar` |
| `NGN` | `Nigerian Naira` |
| `NIO` | `Nicaraguan Córdoba` |
| `NOK` | `Norwegian Krone` |
| `NPR` | `Nepalese Rupee` |
| `NZD` | `New Zealand Dollar` |
| `PAB` | `Panamanian Balboa` |
| `PEN` | `Peruvian Sol` |
| `PGK` | `Papua New Guinean Kina` |
| `PHP` | `Philippine Peso` |
| `PKR` | `Pakistani Rupee` |
| `PLN` | `Polish Złoty` |
| `PYG` | `Paraguayan Guaraní` |
| `QAR` | `Qatari Riyal` |
| `RON` | `Romanian Leu` |
| `RSD` | `Serbian Dinar` |
| `RUB` | `Russian Ruble` |
| `RWF` | `Rwandan Franc` |
| `SAR` | `Saudi Riyal` |
| `SBD` | `Solomon Islands Dollar` |
| `SCR` | `Seychellois Rupee` |
| `SEK` | `Swedish Krona` |
| `SGD` | `Singapore Dollar` |
| `SHP` | `Saint Helenian Pound` |
| `SLL` | `Sierra Leonean Leone` |
| `SOS` | `Somali Shilling` |
| `SRD` | `Surinamese Dollar` |
| `STD` | `São Tomé and Príncipe Dobra` |
| `SZL` | `Swazi Lilangeni` |
| `THB` | `Thai Baht` |
| `TJS` | `Tajikistani Somoni` |
| `TOP` | `Tongan Paʻanga` |
| `TRY` | `Turkish Lira` |
| `TTD` | `Trinidad and Tobago Dollar` |
| `TWD` | `New Taiwan Dollar` |
| `TZS` | `Tanzanian Shilling` |
| `UAH` | `Ukrainian Hryvnia` |
| `UGX` | `Ugandan Shilling` |
| `USD` | `United States Dollar` |
| `UYU` | `Uruguayan Peso` |
| `UZS` | `Uzbekistan Som` |
| `VND` | `Vietnamese Đồng` |
| `VUV` | `Vanuatu Vatu` |
| `WST` | `Samoan Tala` |
| `XAF` | `Central African Cfa Franc` |
| `XCD` | `East Caribbean Dollar` |
| `XOF` | `West African Cfa Franc` |
| `XPF` | `Cfp Franc` |
| `YER` | `Yemeni Rial` |
| `ZAR` | `South African Rand` |
| `ZMW` | `Zambian Kwacha` |
# Document locales
## Document locales supported
List of accepted locales for documents (ISO 639-1).
| Document language | Code |
| ------------------ | ---- |
| German | `de` |
| English | `en` |
| French | `fr` |
| Italian | `it` |
| Norwegian (Bokmål) | `nb` |
| Spanish | `es` |
| Swedish | `sv` |
## How to add a new language
You can contribute to Lago's open-source project by helping us translate documents. The new language will then be added to the list of supported locales and available to the entire Lago Community.
The document template includes translation keys for:
* Invoices related to subscriptions, add-ons and prepaid credits;
* Credit notes;
* Data formatting (e.g. amounts and dates); and
* Syntax (i.e. sentence structure).
The names of your billable metrics, plans, add-ons, coupons and wallets are defined in the app. There are no keys to translate them.
To add a new language:
1. [Download the document template](https://uploads-ssl.webflow.com/635119506e36baf5c267fecd/657743325ca22f3e97f23728_doc-locales-invoice-templates.pdf) to see where each key is located;
2. Use the text file below to provide translations for the new language; and
3. Send the new text file to [hello@getlago.com](mailto:hello@getlago.com), so that we can review it and add it to the codebase.
Thanks for your time and support!
```json
en:
money:
//[AA] format: $4,500.00
format: '%u%n'
decimal_mark: '.'
thousands_separator: ','
date:
formats:
//[AB] format: Dec. 01, 2022
default: '%b. %d, %Y'
abbr_day_names:
- Sun
- Mon
- Tue
- Wed
- Thu
- Fri
- Sat
abbr_month_names:
- Jan
- Feb
- Mar
- Apr
- May
- Jun
- Jul
- Aug
- Sep
- Oct
- Nov
- Dec
day_names:
- Sunday
- Monday
- Tuesday
- Wednesday
- Thursday
- Friday
- Saturday
month_names:
- January
- February
- March
- April
- May
- June
- July
- August
- September
- October
- November
- December
order:
- :year
- :month
- :day
=====================================================================
en:
invoice:
[1.1] document_name: "Invoice"
[1.2] document_tax_name: "Tax invoice"
[1.3] invoice_number: "Invoice Number"
[1.4] issue_date: "Issue Date"
[1.5] payment_term: "Net payment term"
[1.6] payment_term_days: "%{net_payment_term} days"
[1.7] bill_from: "From"
[1.8] bill_to: "Bill to"
[1.9] tax_identification_number: "Tax ID: %{tax_identification_number}"
[1.10] due_date: "Due %{date}"
[1.11] item: "Item"
[1.12] unit: "Unit"
[1.13] unit_price: "Unit price"
[1.14] tax_rate: "Tax rate"
[1.15] amount: "Amount"
[1.16] sub_total_without_tax: "Sub total (excl. tax)"
[1.17] tax_name: "%{name} (%{rate}% on %{amount})"
[1.18] sub_total_with_tax: "Sub total (incl. tax)"
[1.19] credit_notes: "Credit Notes"
[1.20] prepaid_credits: "Prepaid credits"
[1.21] total_due: "Total due"
[1.22] powered_by: "Powered by"
[AC] details: "%{resource} details"
[2.1] date_from: "Fees from"
[2.2] date_to: "to"
[AD] subscription_interval: "%{plan_interval} subscription - %{plan_name}"
[2.3] weekly: "Weekly"
[2.4] monthly: "Monthly"
[2.5] quarterly: "Quarterly"
[2.6] yearly: "Yearly"
graduated & graduated percentage:
[2.7] fee_per_unit_for_the_first: "Fee per unit for the first {to}"
[2.8] fee_per_unit_for_the_next: "Fee per unit for the next §{from} to 8{to}"
[2.9] fee_per_unit_for_the_last: "Fee per unit for {from} and above"
[2.10] flat_fee_for_the_first: "Flat fee for first 8{to}"
[2.11] flat_fee_for_the_next "Flat fee for the next {from} to (to}"
[2.12] flat_fee_for_the_last: "Flat fee for {from} and above"
[2.13] sub_total: "Subtotal"
[2.14] fee_prorated: "The fee is prorated on days of usage, the displayed unit price is an average"
package:
[2.15] free_units_for_the_first: "Free units for the first {count}"
[2.16] fee_per_package: "Fee per package"
[2.17] fee_per_package_unit_price: "§{amount} per {package_size}"
percentage:
[2.18] total_event: "Total event"
[2.19] free_units_per_transaction:
one: "Free units for 1 transaction"
other: "Free units for {count} transactions"
[2.20] percentage_rate_on_amount: "Rate on the amount"
[2.21] fee_per_transaction: "Fixed fee per transaction"
[2.22] adjustment_per_transaction: "Adjustment for min/max per transaction"
[2.23] true_up_metric: "%{metric} • True-up"
[2.24] true_up_details: "Minimum spend of %{min_amount} prorated on days of usage"
volume:
[2.25] fee_per_unit: "Fee per unit"
[2.26] flat_fee_for_all_units: "Flat fee for all units"
[2.27] units_prorated_per_period: "Units prorated per second per %{period}"
[2.28] week: "week"
[2.29] month: "month"
[2.30] quarter: "quarter"
[2.31] year: "year"
[2.32] total: "Total"
[3.1] breakdown: "Breakdown"
[3.2] breakdown_of: "Breakdown of %{fee_filter_display_name}"
[3.3] breakdown_for_days: "Used %{breakdown_duration} out of %{breakdown_total_duration} days"
[3.4] notice_prorated: "Regardless of when an event is received, the unit is not prorated, we charge the full price."
[3.5] notice_full: "If a unit is added or removed during the monthly plan, we calculate the prorated price based on the ratio of days remaining or used to the total number of days in the plan. For instance, if 15 days are left in the plan, we multiply the price by 15/31, and if a unit was used for 10 days, we multiply the price by 10/31."
[4.1] prepaid_credits_with_value: "Prepaid credits - %{wallet_name}"
//For invoices with old versions
total_credits_with_value: "Total credits amount: %{credit_amount} credits"
all_subscriptions: "All subscriptions"
all_usage_based_fees: "All consumption fees"
tax: "Taxes"
fees_from_to_date: "Consumption fees from %{from_date} to %{to_date}"
tax_name_with_details: "%{name} (%{rate}%)"
subscription: "Subscription"
sub_total: "Subtotal"
usage_based_fees: "Consumption fees"
list_of_charges: "List of consumption fees from %{from} to %{to}"
see_breakdown: "See breakdown below"
total_unit_interval: "Total number of units: %{events_count} event(s) for %{units}"
total_unit: "Total number of units: %{units}"
amount_with_tax: "Amount (incl. tax)"
amount_without_tax: "Amount (excl. tax)"
=====================================================================
en:
credit_note:
[5.1] document_name: "Credit note"
[5.2] credit_note_number: "Credit note number"
[5.3] invoice_number: "Invoice number"
[5.4] issue_date: "Issue date"
[5.5] credit_from: "From"
[5.6] credit_to: "Credit to"
[5.7] tax_identification_number: "ID fiscal: %{tax_identification_number}"
[5.8] refunded_notice: "Refunded on %{issuing_date}"
[5.9] credited_notice: "Credited on customer balance on %{issuing_date}"
[5.10] credited_refunded_notice: "Credited on customer balance and refunded on %{issuing_date}"
[5.11] item: "Item"
[5.12] tax_rate: "Tax rate"
[5.13] amount: "Amount (excl. tax)"
[5.14] subscription: "Subscription"
[5.15] true_up_metric: "%{metric} • True-up"
[5.16] coupon_adjustment: "Coupons"
[5.17] sub_total_without_tax: "Sub total (excl. tax)"
[5.18] tax: "%{name} (%{rate}% on %{amount})"
[5.19] credited_on_customer_balance: "Credited on customer balance"
[5.20] refunded: "Refunded"
[5.21] total: "Total"
[5.22] powered_by: "Powered by"
=====================================================================
en:
email:
invoice:
finalized:
[6.1] subject: "Your invoice from {organization_name} #%{invoice_number}"
[6.2] invoice_from: "Invoice from %{organization_name}"
[6.3] due_date: "Due %{date}"
[6.4] invoice_number: "Invoice number"
[6.5] issue_date: "Issue date"
[6.6] download: "Download invoice for details"
credit_note:
created:
[6.7] subject: "Your credit note from %{organization_name} #%{credit_note_number}"
[6.8] credit_note_from: "Credit note from %{organization_name}"
[6.9] refunded_notice: "Refunded on %{date}"
[6.10] credited_notice: "Credited on customer balance on %{date}"
[6.11] credited_refunded_notice: "Credited on customer balance and refunded on %{date}"
[6.12] credit_note_number: "Credit note number"
[6.13] invoice_number: "Invoice number"
[6.14] issue_date: "Issue date"
[6.15] download: "Download invoice for details"
[6.98] questions: "Questions? Contact us at"
[6.99] powered_by_lago: "Powered by"
=====================================================================
en:
customer_portal:
[7.1] powered_by: "Powered by"
[7.2] customer_information: "Customer information"
[7.3] name: "Name"
[7.4] name_not_provided: "Name not provided"
[7.5] legal_name: "Legal name"
[7.6] legal_name_not_provided: "Legal name not provided"
[7.7] legal_number: "Legal number"
[7.8] legal_number_not_provided: "Legal number not provided"
[7.9] tax_id: "Tax ID number"
[7.10] tax_id_not_provided: "Tax ID number not provided"
[7.11] email: "Email"
[7.12] email_not_provided: "Email not provided"
[7.13] address: "Address"
[7.14] address_not_provided: "Address not provided"
[7.15] invoice_history: "Invoice history"
[7.16] invoices_search: "Search invoices"
[7.17] issuing_date: "Issuing date"
[7.18] invoice_number: "Invoice number"
[7.19] amount: "Amount"
[7.20] payment: "Payment "
[7.21] download: "Download PDF"
[7.22] unpaid: "Unpaid"
[7.23] paid: "Paid"
[7.24] invoices_empty_state: "There are currently no invoices attached to this customer. Please check back later, or contact us if you notice any issues."
[7.25] expired_customer_portal_header: "For security reasons, this page has expired"
[7.26] error_customer_portal_header: "Something went wrong token is invalid or has expired"
[7.27] something_went_wrong: "Something went wrong"
[7.28] please_refresh: "Please refresh the page or contact us if the error persists."
[7.29] refresh: "Refresh the page"
[7.30] not_found: "This invoice cannot be found"
[7.31] change_keyword: "Could you enter another keyword?"
```
# Timezones
List of accepted timezones (TZ database).
* `UTC`
* `Africa/Algiers`
* `Africa/Cairo`
* `Africa/Casablanca`
* `Africa/Harare`
* `Africa/Johannesburg`
* `Africa/Monrovia`
* `Africa/Nairobi`
* `America/Argentina/Buenos_Aires`
* `America/Bogota`
* `America/Caracas`
* `America/Chicago`
* `America/Chihuahua`
* `America/Denver`
* `America/Godthab`
* `America/Guatemala`
* `America/Guyana`
* `America/Halifax`
* `America/Indiana/Indianapolis`
* `America/Juneau`
* `America/La_Paz`
* `America/Lima`
* `America/Los_Angeles`
* `America/Mazatlan`
* `America/Mexico_City`
* `America/Monterrey`
* `America/Montevideo`
* `America/New_York`
* `America/Phoenix`
* `America/Puerto_Rico`
* `America/Regina`
* `America/Santiago`
* `America/Sao_Paulo`
* `America/St_Johns`
* `America/Tijuana`
* `Asia/Almaty`
* `Asia/Baghdad`
* `Asia/Baku`
* `Asia/Bangkok`
* `Asia/Chongqing`
* `Asia/Colombo`
* `Asia/Dhaka`
* `Asia/Hong_Kong`
* `Asia/Irkutsk`
* `Asia/Jakarta`
* `Asia/Jerusalem`
* `Asia/Kabul`
* `Asia/Kamchatka`
* `Asia/Karachi`
* `Asia/Kathmandu`
* `Asia/Kolkata`
* `Asia/Krasnoyarsk`
* `Asia/Kuala_Lumpur`
* `Asia/Kuwait`
* `Asia/Magadan`
* `Asia/Muscat`
* `Asia/Novosibirsk`
* `Asia/Rangoon`
* `Asia/Riyadh`
* `Asia/Seoul`
* `Asia/Shanghai`
* `Asia/Singapore`
* `Asia/Srednekolymsk`
* `Asia/Taipei`
* `Asia/Tashkent`
* `Asia/Tbilisi`
* `Asia/Tehran`
* `Asia/Tokyo`
* `Asia/Ulaanbaatar`
* `Asia/Urumqi`
* `Asia/Vladivostok`
* `Asia/Yakutsk`
* `Asia/Yekaterinburg`
* `Asia/Yerevan`
* `Atlantic/Azores`
* `Atlantic/Cape_Verde`
* `Atlantic/South_Georgia`
* `Australia/Adelaide`
* `Australia/Brisbane`
* `Australia/Darwin`
* `Australia/Hobart`
* `Australia/Melbourne`
* `Australia/Perth`
* `Australia/Sydney`
* `Europe/Amsterdam`
* `Europe/Athens`
* `Europe/Belgrade`
* `Europe/Berlin`
* `Europe/Bratislava`
* `Europe/Brussels`
* `Europe/Bucharest`
* `Europe/Budapest`
* `Europe/Copenhagen`
* `Europe/Dublin`
* `Europe/Helsinki`
* `Europe/Istanbul`
* `Europe/Kaliningrad`
* `Europe/Kiev`
* `Europe/Lisbon`
* `Europe/Ljubljana`
* `Europe/London`
* `Europe/Madrid`
* `Europe/Minsk`
* `Europe/Moscow`
* `Europe/Paris`
* `Europe/Prague`
* `Europe/Riga`
* `Europe/Rome`
* `Europe/Samara`
* `Europe/Sarajevo`
* `Europe/Skopje`
* `Europe/Sofia`
* `Europe/Stockholm`
* `Europe/Tallinn`
* `Europe/Vienna`
* `Europe/Vilnius`
* `Europe/Volgograd`
* `Europe/Warsaw`
* `Europe/Zagreb`
* `Europe/Zurich`
* `GMT+12`
* `Pacific/Apia`
* `Pacific/Auckland`
* `Pacific/Chatham`
* `Pacific/Fakaofo`
* `Pacific/Fiji`
* `Pacific/Guadalcanal`
* `Pacific/Guam`
* `Pacific/Honolulu`
* `Pacific/Majuro`
* `Pacific/Midway`
* `Pacific/Noumea`
* `Pacific/Pago_Pago`
* `Pacific/Port_Moresby`
* `Pacific/Tongatapu`
# Create a subscription
POST /subscriptions
This endpoint assigns a plan to a customer, creating or modifying a subscription. Ideal for initial subscriptions or plan changes (upgrades/downgrades).
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "premium",
"name": "Repository A",
"external_id": "my_sub_1234567890",
"billing_time": "anniversary",
"ending_at": "2022-10-08T00:00:00Z",
"subscription_at": "2022-08-08T00:00:00Z",
"plan_overrides": {
"amount_cents": 10000,
"amount_currency": "USD",
"description": "Plan for early stage startups.",
"invoice_display_name": "Startup plan",
"name": "Startup",
"tax_codes": [
"french_standard_vat"
],
"trial_period": 5,
"charges": [
{
"id": "cha_12345",
"billable_metric_id": "bm_12345",
"invoice_display_name": "Setup",
"min_amount_cents": 0,
"tax_codes": [
"standard_vat"
],
"properties": {
"graduated_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
},
{
"id": "cha_67890",
"billable_metric_id": "bm_67890",
"invoice_display_name": "FX Transfer",
"min_amount_cents": 0,
"properties": {
"graduated_percentage_ranges": [
{
"from_value": 0,
"to_value": 10,
"rate": "1",
"flat_amount": "10"
}
]
}
},
{
"id": "cha_111213",
"billable_metric_id": "bm_111213",
"invoice_display_name": "API calls",
"min_amount_cents": 0,
"properties": {
"amount": "30",
"free_units": 100,
"package_size": 1000
}
},
{
"id": "cha_141516",
"billable_metric_id": "bm_141516",
"invoice_display_name": "Interchange",
"min_amount_cents": 0,
"properties": {
"rate": "1",
"fixed_amount": "0.5",
"free_units_per_events": 5,
"free_units_per_total_aggregation": "500",
"per_transaction_max_amount": "3.75",
"per_transaction_min_amount": "1.75"
}
},
{
"id": "cha_171819",
"billable_metric_id": "bm_171819",
"invoice_display_name": "Seats",
"min_amount_cents": 0,
"properties": {
"volume_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
},
{
"id": "cha_202122",
"billable_metric_id": "bm_202122",
"invoice_display_name": "Interchange",
"min_amount_cents": 0,
"filters": [
{
"values": {
"cloud": ["aws"],
"region": ["us-east-1"]
},
"properties": {
"graduated_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
}
]
}
]
}
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Subscription
client = Client(api_key='__YOUR_API_KEY__')
subscription = Subscription(
external_customer_id="5eb02857-a71e-4ea2-bcf9-57d8885990ba",
plan_code="startup_plan",
external_id="sub_id_123456789",
name="Repository A",
subscription_at="2022-08-08T00:00:00Z",
ending_at= "2023-08-08T00:00:00Z",
billing_time="anniversary"
)
try:
client.subscriptions.create(subscription)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.subscriptions.create(
external_customer_id: "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
plan_code: "startup_plan",
external_id: "sub_id_123456789",
name: "Repository A",
subscription_at: "2022-08-08T00:00:00Z",
ending_at: "2023-08-08T00:00:00Z",
billing_time: "anniversary"
)
```
```js Javascript
import { Client, SubscriptionObject } from "lago-javascript-client";
const subscriptionObject = {
external_customer_id: "5eb02857-a71e-4ea2-bcf9-57d8885990ba",
plan_code: "statup_plan",
external_id: "sub_id_123456789",
name: "Repository A",
subscription_at: "2022-08-08T00:00:00Z",
ending_at: "2023-08-08T00:00:00Z",
billing_time: "anniversary" as SubscriptionObject["billingTime"],
};
await client.subscriptions.createSubscription({
subscription: subscriptionObject,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
subscriptionInput := &lago.SubscriptionInput{
ExternalCustomerID: "5eb02857-a71e-4ea2-bcf9-57d8885990ba",
PlanCode: "startup_plan",
SubscriptionAt: "2022-08-08T00:00:00Z",
EndingAt: "2023-08-08T00:00:00Z",
BillingTime: lago.Anniversary,
}
subscription, err := lagoClient.Subscription().Create(subscriptionInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// subscription is *lago.Subscription
fmt.Println(subscription)
}
```
# List all subscriptions
GET /subscriptions
This endpoint retrieves all active subscriptions.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/subscriptions?external_customer_id=123&plan_code=starter&status[]=pending" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.subscriptions.find_all({'external_customer_id': '123'})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.subscriptions.get_all({ external_customer_id: '123'})
```
```js Javascript
await client.subscriptions.findAllSubscriptions({
external_customer_id: "123",
page: 1,
});
```
# Retrieve subscription lifetime usage
GET /subscriptions/{external_id}/lifetime_usage
This endpoint allows you to retrieve the total lifetime usage of a subscription.
# Retrieve a subscription
GET /subscriptions/{external_id}
This endpoint retrieves a specific subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/subscriptions/:external_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.subscriptions.find('externalId')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.subscriptions.get('external_id')
```
```js Javascript
await client.subscriptions.findSubscription("external_id");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
subscriptionResult, err := lagoClient.Subscription().Get("__YOUR_SUBSCRIPTION_EXTERNAL_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// subscription is *lago.Subscription
fmt.Println(subscription)
}
```
# The lifetime usage object
This object represents the total lifetime usage of a subscription, particularly useful for progressive billing.
# The subscription object
This object represents the assignation of plan to one of the customer of your business.
# Terminate a subscription
DELETE /subscriptions/{external_id}
This endpoint allows you to terminate a subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_ID="__YOUR_SUBSCRIPTION_ID__"
curl --location --request DELETE "$LAGO_URL/api/v1/subscriptions/$EXTERNAL_ID?status=pending" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.subscriptions.destroy('external_id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.subscriptions.destroy("5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba")
```
```js Javascript
await client.subscriptions.destroySubscription("external_id");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
subscription, err := lagoClient.Subscription().Terminate("__EXTERNAL_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// subscription is *lago.Subscription
fmt.Println(subscription)
}
```
# Update a subscription
PUT /subscriptions/{external_id}
This endpoint allows you to update a subscription.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/subscriptions/:id" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"name": "Repository B",
"ending_at": "2022-10-08T00:00:00Z",
"subscription_at": "2022-08-08T00:00:00Z",
"plan_overrides": {
"amount_cents": 10000,
"amount_currency": "USD",
"description": "Plan for early stage startups.",
"invoice_display_name": "Startup plan",
"name": "Startup",
"tax_codes": [
"french_standard_vat"
],
"trial_period": 5,
"charges": [
{
"id": "cha_12345",
"billable_metric_id": "bm_12345",
"invoice_display_name": "Setup",
"min_amount_cents": 0,
"tax_codes": [
"standard_vat"
],
"properties": {
"graduated_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
},
{
"id": "cha_67890",
"billable_metric_id": "bm_67890",
"invoice_display_name": "FX Transfer",
"min_amount_cents": 0,
"properties": {
"graduated_percentage_ranges": [
{
"from_value": 0,
"to_value": 10,
"rate": "1",
"flat_amount": "10"
}
]
}
},
{
"id": "cha_111213",
"billable_metric_id": "bm_111213",
"invoice_display_name": "API calls",
"min_amount_cents": 0,
"properties": {
"amount": "30",
"free_units": 100,
"package_size": 1000
}
},
{
"id": "cha_141516",
"billable_metric_id": "bm_141516",
"invoice_display_name": "Interchange",
"min_amount_cents": 0,
"properties": {
"rate": "1",
"fixed_amount": "0.5",
"free_units_per_events": 5,
"free_units_per_total_aggregation": "500",
"per_transaction_max_amount": "3.75",
"per_transaction_min_amount": "1.75"
}
},
{
"id": "cha_171819",
"billable_metric_id": "bm_171819",
"invoice_display_name": "Seats",
"min_amount_cents": 0,
"properties": {
"volume_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
},
{
"id": "cha_202122",
"billable_metric_id": "bm_202122",
"invoice_display_name": "Interchange",
"min_amount_cents": 0,
"filters": [
{
"values": {
"cloud": ["aws"],
"region": ["us-east-1"]
},
"properties": {
"graduated_ranges": [
{
"from_value": 0,
"to_value": 10,
"flat_amount": "10",
"per_unit_amount": "0.5"
}
]
}
}
]
}
]
}
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Subscription
client = Client(api_key='__YOUR_API_KEY__')
update_params = Subscription(name='new name', subscription_at='2022-08-08T00:00:00Z', ending_at= '2023-08-08T00:00:00Z')
try:
client.subscriptions.update(update_params, 'id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
update_params = { name: 'new name', subscription_at: '2022-08-08T00:00:00Z', ending_at: '2022-08-08T00:00:00Z' }
client.subscriptions.update(update_params, 'id')
```
```js Javascript
await client.subscriptions.updateSubscription("external_id", {
subscription: {
name: "new name",
subscription_at: "2022-08-08T00:00:00Z",
ending_at: "2023-08-08T00:00:00Z",
},
});
```
# Update subscription lifetime usage
PUT /subscriptions/{external_id}/lifetime_usage
This endpoint allows you to update the total lifetime usage of a subscription for migration purposes.
# Create a tax rate
POST /taxes
This endpoint creates a new tax representing a customizable tax rate applicable to either the organization or a specific customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/taxes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"tax": {
"name": "TVA",
"code": "french_standard_vat",
"rate": "20.0",
"description": "French standard VAT",
"applied_to_organization": false
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Tax
client = Client(api_key='__YOUR_API_KEY__')
tax = Tax(
name="TVA",
code="french_standard_vat",
rate="20.0",
description="French standard VAT",
applied_to_organization=false
)
try:
client.taxes.create(tax)
except LagoApiError as e:
# do something on error or raise your own exception
repair_broken_state(e)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
tax = {
name: "TVA",
code: "french_standard_vat",
rate: "20.0",
description: "French standard VAT",
applied_to_organization: false
}
client.taxes.create(tax)
```
```js Javascript
const taxObject = {
name: "TVA",
code: "french_standard_vat",
rate: "20.0",
description: "French standard VAT",
applied_to_organization: false,
};
await client.taxes.createTax({ tax: taxObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
taxInput := &lago.TaxInput{
Name: "TVA",
Code: "french_standard_vat",
Rate: "20.0",
Description: "French standard VAT",
AppliedToOrganization: false,
}
tax, err := lagoClient.Tax().Create(taxInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// tax is *lago.Tax
fmt.Println(tax)
}
```
# Delete a tax rate
DELETE /taxes/{code}
This endpoint is used to delete a tax.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/taxes/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.taxes.destroy('code')
except LagoApiError as e:
repair_broken_state(e)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.taxes.destroy('code')
```
```js Javascript
await client.taxes.destroyTax('code')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
tax, err := lagoClient.Tax().Delete("__YOUR_TAX_CODE__")
if err != nil {
panic(err)
}
fmt.Println(tax)
}
```
# List all tax rates
GET /taxes
This endpoint retrieves all existing taxes representing a customizable tax rate applicable to either the organization or a specific customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/taxes?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.taxes.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.taxes.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.taxes.findAllTaxes({ per_page: 2, page: 3 });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
taxListInput := &lago.TaxListInput{
PerPage: 1,
Page: 1,
}
taxResult, err := lagoClient.Tax().GetList(taxListInput)
if err != nil {
panic(err)
}
fmt.Println(taxResult)
}
```
# Retrieve a tax rate
GET /taxes/{code}
This endpoint retrieves an existing tax representing a customizable tax rate applicable to either the organization or a specific customer. The tax is identified by its unique code.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/taxes/:code" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.taxes.find('code')
except LagoApiError as e:
repair_broken_state(e)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.taxes.get('code')
```
```js Javascript
await client.taxes.findTax("code");
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
tax, err := lagoClient.Tax().Get("__YOUR_TAX_CODE__")
if err != nil {
panic(err)
}
fmt.Println(tax)
}
```
# The tax object
This object represents a customizable tax rate applicable to either the organization or a specific customer.
# Update a tax rate
PUT /taxes/{code}
This endpoint updates an existing tax representing a customizable tax rate applicable to either the organization or a specific customer.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/taxes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"tax": {
"name": "french vat",
"code": "french_vat_2",
"rate": 20.00,
"description": "Standard VAT",
"applied_to_organization": false
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Tax
client = Client(api_key='__YOUR_API_KEY__')
tax = Tax(
name="TVA",
code="french_standard_vat",
rate="20.0",
description="French standard VAT",
applied_to_organization=false
)
try:
client.taxes.update(tax, "french_standard_vat")
except LagoApiError as e:
# do something on error or raise your own exception
repair_broken_state(e)
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
tax = {
name: "TVA",
code: "french_standard_vat",
rate: "20.0",
description: "French standard VAT",
applied_to_organization: false
}
client.taxes.update(tax, "french_standard_vat")
```
```js Javascript
const taxObject = {
name: "TVA",
code: "french_standard_vat",
rate: "20.0",
description: "French standard VAT",
applied_to_organization: false,
};
await client.taxes.updateTax("french_standard_vat", { tax: taxObject });
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().SetApiKey("__YOUR_API_KEY__")
taxInput := &lago.TaxInput{
Name: "TVA",
Code: "french_standard_vat",
Rate: "20.0",
Description: "French standard VAT",
AppliedToOrganization: false,
}
tax, err := lagoClient.Tax().Update(taxInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// tax is *lago.Tax
fmt.Println(tax)
}
```
# Create a wallet
POST /wallets
This endpoint is used to create a wallet with prepaid credits.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"name": "Prepaid",
"rate_amount": "1.5",
"paid_credits": "20.0",
"granted_credits": "10.0",
"currency": "USD",
"expiration_at": "2022-07-07",
"external_customer_id": "hooli_1234"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Wallet
client = Client(api_key='__YOUR_API_KEY__')
wallet = Wallet(
name='Prepaid',
rate_amount='1.5',
paid_credits='20.0',
granted_credits='10.0',
currency='USD',
expiration_at='2022-07-07T23:59:59Z',
external_customer_id='hooli_1234'
)
try:
client.wallets.create(wallet)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallets.create({
name: 'Prepaid',
rate_amount: '1.5',
paid_credits: '20.0',
granted_credits: '10.0',
currency: 'USD',
expiration_at: '2022-07-07T23:59:59Z',
external_customer_id: 'hooli_1234'
})
```
```js Javascript
await client.wallets.createWallet({
wallet: {
name: "Prepaid",
currency: "USD",
rate_amount: 1.5,
paid_credits: 20.0,
granted_credits: 10.0,
expiration_at: "2022-07-07T23:59:59Z",
external_customer_id: "hooli_1234",
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
walletInput := &lago.WalletInput{
Name: "Prepaid",
RateAmount: "1.5",
PaidCredits: "20.0"
GrantedCredits: "10.0",
Currency: "USD",
ExpirationAt: "2022-07-07T23:59:59Z",
ExternalCustomerID: "hooli_1234",
}
wallet, err := lagoClient.Wallet().Create(walletInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.Wallet
fmt.Println(wallet)
}
```
# List all wallets
GET /wallets
This endpoint is used to list all wallets with prepaid credits.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/wallets?external_customer_id&per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.wallets.find_all({'external_customer_id': hooli_1234, 'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallets.get_all({ external_customer_id: hooli_1234, per_page: 2, page: 3 })
```
```js Javascript
await client.wallets.findAllWallets({
external_customer_id: "hooli_1234",
per_page: 2,
page: 3,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
walletListInput := &lago.WalletListInput{
PerPage: 10,
Page: 1,
ExternalCustomerID: hooli_1234
}
walletResult, err := lagoClient.Wallet().GetList(walletListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.WalletResult
fmt.Println(walletResult)
}
```
# List all wallet transactions
GET /wallets/{lago_id}/wallet_transactions
This endpoint is used to list all wallet transactions.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/wallets/:id/wallet_transactions?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.wallet_transactions.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallet_transactions.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.wallets.findAllWalletTransactions("wallet-id", {
per_page: 2,
page: 3,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
walletTransactionListInput := &lago.WalletTransactionListInput{
PerPage: 1,
Page: 1,
WalletId: 12345,
}
walletTransactionResult, err := lagoClient.WalletTransaction().GetList(walletTransactionListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// walletTransactionResult is *lago.WalletTransactionResult
fmt.Println(walletTransactionResult)
}
```
# Retrieve a wallet
GET /wallets/{lago_id}
This endpoint is used to retrieve an existing wallet with prepaid credits.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/wallets/:id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.wallets.find('id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallets.get('id')
```
```js Javascript
await client.wallets.findWallet('wallet-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
wallet, err := lagoClient.Wallet().Get("__ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.Wallet
fmt.Println(wallet)
}
```
# Terminate a wallet
DELETE /wallets/{lago_id}
This endpoint is used to terminate an existing wallet with prepaid credits.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/wallets/:wallet_id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.wallets.destroy('id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallets.destroy('id')
```
```js Javascript
await client.wallets.destroyWallet('wallet-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
wallet, err := lagoClient.Wallet().Delete("__ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.Wallet
fmt.Println(wallet)
}
```
# Top-up a wallet
POST /wallet_transactions
This endpoint is used to top-up an active wallet.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallet_transactions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet_transaction": {
"wallet_id": "wallet_1234",
"paid_credits": "20.0",
"granted_credits": "10.0"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import WalletTransaction
client = Client(api_key='__YOUR_API_KEY__')
transaction = WalletTransaction(
wallet_id='wallet_1234',
paid_credits='20.0',
granted_credits='10.0'
)
try:
client.wallet_transactions.create(transaction)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallet_transactions.create({
wallet_id: 'wallet_1234',
paid_credits: '20.0',
granted_credits: '10.0'
})
```
```js Javascript
await client.walletTransactions.createWalletTransaction({
wallet_transaction: {
wallet_id: "wallet_1234",
paid_credits: 20.0,
granted_credits: 10.0,
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
walletTransactionInput := &lago.WalletTransactionInput{
WalletId: "wallet_1234",
PaidCredits: "20.0"
GrantedCredits: "10.0",
}
transactions, err := lagoClient.WalletTransaction().Create(walletTransactionInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.Wallet
fmt.Println(transactions)
}
```
# Update a wallet
PUT /wallets/{lago_id}
This endpoint is used to update an existing wallet with prepaid credits.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/wallets/:lago_id" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"name": "Prepaid Credits",
"expiration_at": "2022-07-07T23:59:59Z"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import Wallet
client = Client(api_key='__YOUR_API_KEY__')
wallet = Wallet(
name='Prepaid Credits',
expiration_at='2022-07-07T23:59:59Z'
)
try:
client.wallets.update(wallet, '__WALLET_ID__')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.wallets.update({
name: 'Prepaid Credits',
expiration_at: '2022-07-07T23:59:59Z',
}, '__WALLET_ID__')
```
```js Javascript
await client.wallets.updateWallet("wallet-id", {
wallet: { name: "Prepaid Credits", expiration_at: "2022-07-07T23:59:59Z" },
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
walletInput := &lago.WalletInput{
Name: "Prepaid Credits",
ExpirationAt: "2022-07-07T23:59:59Z"
}
wallet, err := lagoClient.Wallet().Update(walletInput, "__WALLET_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// wallet is *lago.Wallet
fmt.Println(wallet)
}
```
# The wallet object
This object represents a wallet, holding free or prepaid credits.
# The wallet transaction object
This object represents a wallet transaction. It is used for topping up or voiding prepaid credits.
# Create a webhook endpoint
POST /webhook_endpoints
This endpoint is used to create a webhook endpoint.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/webhook_endpoints" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"webhook_endpoint": {
"webhook_url": "https://foo.bar",
"signature_algo": "hmac"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import WebhookEndpoint
client = Client(api_key='__YOUR_API_KEY__')
webhook_endpoint = WebhookEndpoint(
webhook_url='https://foo.bar',
signature_algo: 'hmac'
)
try:
client.webhook_endpoints.create(webhook_endpoint)
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.webhook_endpoints.create({
webhook_url: 'https://foo.bar',
signature_algo: 'hmac'
})
```
```js Javascript
await client.webhookEndpoints.createWebhookEndpoint({
webhook_endpoint: {
webhook_url: "https://foo.bar",
signature_algo: "hmac",
},
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
webhookEndpointInput := &lago.WebhookEndpointInput{
WebhookURL: "https://foo.bar"
}
webhookEndpoint, err := lagoClient.WebhookEndpoint().Create(webhookEndpointInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// webhookEndpoint is *lago.WebhookEndpoint
fmt.Println(webhookEndpoint)
}
```
# Delete a webhook endpoint
DELETE /webhook_endpoints/{id}
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/webhook_endpoints/:id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.webhook_endpoints.destroy('id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.webhook_endpoints.destroy('id')
```
```js Javascript
await client.webhookEndpoints.deleteWebhookEndpoint('id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
webhookEndpoint, err := lagoClient.WebhookEndpoint().Delete("id")
if err != nil {
// Error is *lago.Error
panic(err)
}
// webhookEndpoint is *lago.WebhookEndpoint
fmt.Println(webhookEndpoint)
}
```
# Retrieve a webhook endpoint
GET /webhook_endpoints
This endpoint is used to list all webhook endpoints.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/webhook_endpoints?per_page=2&page=1" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.webhook_endpoints.find_all({'per_page': 2, 'page': 1})
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.webhook_endpoints.get_all({ per_page: 2, page: 3 })
```
```js Javascript
await client.webhookEndpoints.findAllWebhookEndpoints({
per_page: 2,
page: 3,
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
webhookEndpointListInput := &lago.WebhookEndpointListInput{
PerPage: 10,
Page: 1
}
webhookEndpointResult, err := lagoClient.WebhookEndpoint().GetList(WebhookEndpointListInput)
if err != nil {
// Error is *lago.Error
panic(err)
}
// webhookEndpointResult is *lago.WebhookEndpointResult
fmt.Println(webhookEndpointResult)
}
```
# List all webhook endpoints
GET /webhook_endpoints/{lago_id}
This endpoint is used to retrieve an existing webhook endpoint.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/webhook_endpoints/:id" \
--header "Authorization: Bearer $API_KEY"
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
client = Client(api_key='__YOUR_API_KEY__')
try:
client.webhook_endpoints.find('id')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.webhook_endpoints.get('id')
```
```js Javascript
await client.webhookEndpoints.findWebhookEndpoint('webhook-endpoint-id')
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
webhookEndpoint, err := lagoClient.WebhookEndpoint().Get("__ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// webhookEndpoint is *lago.WebhookEndpoint
fmt.Println(webhookEndpoint)
}
```
# Update a webhook endpoint
PUT /webhook_endpoints/{lago_id}
This endpoint is used to update an existing webhook endpoint.
```bash cURL
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/webhook_endpoints/:lago_id" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"webhook_endpoint": {
"webhook_url": "https://foo.bar",
"signature_algo": "hmac"
}
}'
```
```python Python
from lago_python_client.client import Client
from lago_python_client.exceptions import LagoApiError
from lago_python_client.models import WebhookEndpoint
client = Client(api_key='__YOUR_API_KEY__')
webhook_endpoint = WebhookEndpoint(
webhook_url='https://foo.bar',
signature_algo: 'hmac'
)
try:
client.webhook_endpoints.update(webhook_endpoint, '__WEBHOOK_ENDPOINT_ID__')
except LagoApiError as e:
repair_broken_state(e) # do something on error or raise your own exception
```
```ruby Ruby
require 'lago-ruby-client'
client = Lago::Api::Client.new(api_key: '__YOUR_API_KEY__')
client.webhook_endpoints.update({
webhook_url: 'https://foo.bar',
signature_algo: 'hmac'
}, '__WEBHOOK_ENDPOINT_ID__')
```
```js Javascript
await client.webhook_endpoints.updateWebhookEndpoint("webhook-endpoint-id", {
webhook_endpoint: { webhook_url: "https://foo.bar" },
});
```
```go Go
import "fmt"
import "github.com/getlago/lago-go-client"
func main() {
lagoClient := lago.New().
SetApiKey("__YOUR_API_KEY__")
webhookEndpointInput := &lago.WebhookEndpointInput{
WebhookURL: "https://foo.bar"
}
webhookEndpoint, err := lagoClient.WebhookEndpoint().Update(webhookEndpointInput, "__WEBHOOK_ENDPOINT_ID__")
if err != nil {
// Error is *lago.Error
panic(err)
}
// webhookEndpoint is *lago.WebhookEndpoint
fmt.Println(webhookEndpoint)
}
```
# The webhook endpoint object
This object represents the webhook endpoint used for listening to Lago’s events
# Format & Signature
Webhooks are HTTP notifications sent from Lago to your application.
The messages are sent as a `POST` to the URL defined in the settings of your
Lago workspace.
## Message format[](#message-format "Direct link to heading")
`POST __WEBHOOK_URL__`
```json
{
"webhook_type": "__TYPE__",
"object_type": "OBJECT_TYPE",
"__OBJECT__": {}
}
```
## Signature[](#signature "Direct link to heading")
Allong with the payload the message contains both `X-Lago-Signature` and `X-Lago-Signature-Algorithm` HTTP header.
It is used to ensure the message is Coming from Lago and that the message has not been altered.
To verify the signature, you must decode the signature and compare the result with the body of the webhook.
You can choose between 2 differents signatures algorithm during your webhook endpoints creation, `hmac` or `jwt`.
Please note that `jwt` is our original signature and is used by default.
### JWT Signature
#### 1. Retrieve the public key[](#1-retrieve-the-public-key "Direct link to heading")
```py Python
from lago_python_client import Client
client = Client(api_key='__YOUR_API_KEY__')
webhooks_public_key = client.webhooks().public_key()
```
```js Node.js
import Client from "lago-nodejs-client";
let client = new Client("__YOUR_API_KEY__");
let webhooksPublicKey = client.webhookPublicKey();
```
```ruby Ruby
require 'net/http'
api_key = "__YOUR_API_KEY__"
uri = URI('https://api.getlago.com/api/v1/webhooks/public_key')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
response = http.send_request(
'GET',
uri.request_uri,
'',
{ 'Authorization' => "Bearer #{api_key}" }
)
webhooks_public_key = response.body
```
You should persist the public key on your side to avoid querying it for each
webhook.
#### 2. Decode and validate the signature[](#2-decode-and-validate-the-signature "Direct link to heading")
```py Python
import jwt
decoded_signature = jwt.decode(
request.headers.get('X-Lago-Signature'),
webhooks_public_key,
algorithms=['RS256'],
issuer="https://api.getlago.com"
)
decoded_signature['data'] == request.body
```
```js Node.js
import jwt from "jsonwebtoken";
let token = request.header("X-Lago-Signature");
jwt.verify(
token,
webhooksPublicKey,
{
algorithms: ["RS256"],
issuer: "https://api.getlago.com",
},
function (err, payload) {
payload === request.body;
}
);
```
```ruby Ruby
require 'openssl'
require 'jwt'
decoded_signature = JWT.decode(
request.headers['X-Lago-Signature'],
OpenSSL::PKey::RSA.new(Base64.decode64(webhooks_public_key)),
true,
{
algorithm: 'RS256',
iss: "https://api.getlago.com",
verify_iss: true,
},
).first
decoded_signature['data'] == request.body
```
### HMAC Signature
#### Decode and validate the signature
```py Python
import hmac
import base64
calc_sig = hmac.new(LAGO_API_KEY, request.body.encode(), 'sha256').digest()
base64_sig = base64.b64encode(calc_sig).decode()
request.headers.get('X-Lago-Signature') == base64_sig
```
```js Node.js
import crypto from 'crypto';
const signature = request.header('X-Lago-Signature')
const hmac = crypto.createHmac('sha256', 'YOUR_ORGANIZATION_API_KEY')
hmac.update(request.body)
const encodedBody = hmac.digest().toString('base64')
signature == encodedBody
```
```ruby Ruby
require 'openssl'
signature = request.headers['X-Lago-Signature']
hmac = OpenSSL::HMAC.digest('sha-256', 'YOUR_ORGANIZATION_API_KEY', request.body)
base64_hmac = Base64.strict_encode64(hmac)
base64_hmac == signature
```
```php PHP
$signature = $_SERVER['X-Lago-Signature'];
$requestBody = file_get_contents('php://input');
$hmac = hash_hmac('sha256', $requestBody, 'YOUR_ORGANIZATION_API_KEY', true);
$base64Signature = base64_encode($hmac);
$valid = hash_equals($signature, $base64Signature);
```
# Messages
Below is a list of the event types we currently send. Please note that additional event types may be introduced in the future, so your code should be flexible enough to accommodate new types as they arise. Our objective is to maintain a consistent and predictable event structure, making it easier to integrate and handle messages, along with the objects they affect.
## Credit notes and refunds
[Credit note object](/api-reference/credit-notes/credit-note-object). Sent when a new credit note has been issued for a customer. This will allow your application to proceed with the refund.
[Credit note object](/api-reference/credit-notes/credit-note-object). Sent when the PDF file has been generated for a credit note. This will allow your application to retrieve the PDF credit note.
`credit_note_payment_provider_refund_error` object. Sent when there is an error related to the refund process (i.e. the payment provider cannot refund the customer).
## Customers
### External payment providers
[Customer object](/api-reference/customers/object). Sent when a customer is successfully created in the payment provider’s application. This allows you to retrieve the identifier assigned to the customer by the payment service provider.
`payment_provider_customer_checkout_url` object. Sent when a checkout link is issued for a customer.
`payment_provider_customer_error` object. Sent when there is an error related to the creation of a customer in the payment provider’s system.
`payment_provider_invoice_payment_error` object. Sent when there is an error related to the payment process. Usually occurs when no valid payment method is defined for the customer in the payment service provider’s application.
`payment_dispute_lost` object. Sent whenever a dispute or a chargeback is lost within your payment provider.
### External accounting providers
[Customer object](/api-reference/customers/object). Sent when a customer is successfully created in the accounting provider’s application (like NetSuite). This allows you to retrieve the identifier assigned to the customer by the accounting service provider.
`accounting_provider_customer_error` object. Sent when there is an error related to the accounting provider sync. Usually occurs when something went wrong in the accounting service provider’s application.
### External tax providers
`tax_provider_error` object. Sent when there is an error related to the tax provider sync. This usually occurs due to issues with item mappings, customer definitions, or within the service provider’s application.
## Event ingestion
Sent by the health check process when some events received in the previous hour do not match the validation rules.
This webhook is deprecated and no longer sent in Lago `v0.50.0-beta` and above. It was sent when there was an error related to the creation of an event.
## Invoices
[Invoice object](/api-reference/invoices/invoice-object). Sent when a new invoice is in draft.
[Invoice object](/api-reference/invoices/invoice-object). Sent when an invoice is finalized.
This event serves as a signal to your application that the invoice processing is complete and you can proceed with the necessary billing actions or procedures.
[Invoice object](/api-reference/invoices/invoice-object). Sent when a one-off invoice is created. Only add-ons can be applied to one-off invoices.
[Invoice object](/api-reference/invoices/invoice-object). Sent when prepaid credits have been paid and added to the customer's wallet. You can use this information to generate a PDF invoice or collect the payment.
[Invoice object](/api-reference/invoices/invoice-object). Sent when the PDF file has been generated for a customer invoice. This will allow your application to retrieve the PDF invoice.
[Invoice object](/api-reference/invoices/invoice-object). Sent when the payment status of an invoice is updated based on information provided by the payment provider.
[Invoice object](/api-reference/invoices/invoice-object). Sent when the payment of an invoice is considered as overdue.
[Invoice object](/api-reference/invoices/invoice-object). Sent when an invoice is voided.
## Payments
This message is triggered when a payment requires additional validation or confirmation, typically via 3D Secure (3DS). This is commonly seen in regions like India or when enhanced customer authentication is necessary.
The `url` field contains the checkout link that initiates 3D Secure (3DS) validation for your customers. The `return_url` is the page displayed once the 3DS process is completed.
[Payment request object](/api-reference/payment-requests/payment-request-object). Sent when a manual payment request has been triggered, to request payment for the overdue balance.
[Payment request object](/api-reference/payment-requests/payment-request-object). Sent when the payment attached to a payment request has failed. The `provider_error` field indicates the error code and message from the payment provider.
[Payment request object](/api-reference/payment-requests/payment-request-object). Sent when the payment attached to a payment request is updated to a new payment status, through the \`payment\_status field.
## Subscriptions and fees
[Fee object](/api-reference/fees/fee-object). Sent when a fee for a charge to be paid in advance is created. You can use this information to collect the payment of the `pay_in_advance` fee. Useful for fintech companies that need to create a statement of transactions without invoicing.
[Subscription object](/api-reference/subscriptions/subscription-object). Sent when a subscription starts.
[Subscription object](/api-reference/subscriptions/subscription-object). Alert for imminent termination of subscriptions with set end dates, sent 45 days and 15 days prior (at fixed intervals).
[Subscription object](/api-reference/subscriptions/subscription-object). Sent when a subscription is terminated.
[Subscription object](/api-reference/subscriptions/subscription-object). Sent when the free trial is ended for a subscription.
[Subscription object](/api-reference/subscriptions/subscription-object). Sent when a progressive billing threshold has been crossed.
## Wallets and prepaid credits
[Wallet transaction object](/api-reference/wallets/wallet-transaction-object). Sent when a wallet transaction is updated. For example, when wallet transaction is marked as settled.
[Wallet object](/api-reference/wallets/wallet-object). Sent when the ongoing balance is negative or equal to 0.
# Product updates
New updates and improvements to Lago.
## Automatic Dunning: Payment reminders on autopilot
For businesses billing on usage, keeping payments timely is essential. That's why we're introducing **Automatic Dunning**—a hands-off way to manage overdue invoices and keep cash flow steady.
With Automatic Dunning, you can **set up tailored reminder campaigns** for different customer groups. Once activated, **these campaigns run on autopilot**, sending scheduled email reminders for any unpaid invoices. Reminders will keep going until the payment is made or you adjust the settings.
Automatic Dunning keeps your payment reminders on autopilot, so you can focus on what matters while your billing engine handles collections in the background.
[Learn more](../guide/dunning/automatic-dunning)
## Customizable Rounding for usage metrics
Previously, usage rounding in Lago was limited to a default precision. Now, with **Customizable Rounding Rules**, you have full control over how usage-based metrics are rounded.
Choose from these rounding options:
* **Ceil**: Always round up to the nearest integer.
* **Floor**: Always round down to the nearest integer.
* **Round**: Round to the nearest integer using standard rounding rules.
Additionally, you can specify a **precision level**—positive or negative—allowing you to round usage to a set number of decimals.
[Learn more](../guide/billable-metrics/rounding)
## Build any usage-Based Metric with SQL Expressions
Previously, usage-based metrics in Lago were powered by a single field—ideal for simplicity but limited in flexibility. Now, we are giving you complete control with SQL Expressions.
**With SQL Expressions, you can build metrics tailored to your needs**. Use advanced math operations, concatenations, rounding, and more to create precise, custom metrics that reflect your unique usage patterns.
**Custom expressions allow you to define more advanced computation logic** by dynamically using any event field within your expression. Here are a few examples:
* **Concatenation:** `CONCAT(value1, '_', value2)`
* **Math operations:** `((value1 * value2) / value3)`
* **Rounding:** `ROUND(value1 / value2)`
```SQL SQL Expression example
CEIL((event.properties.ended_at - event.timestamp) / 3600)
```
[Learn more](../guide/billable-metrics/sql-expressions)
## Cascade plan editions to overridden subscriptions
You have now the flexibility to decide whether changes made to the parent plan should automatically cascade to all overridden subscriptions.
For instance, if you add a new charge to the parent plan, it will immediately reflect in the overridden subscriptions, ensuring that all pricing updates are seamlessly applied across your entire customer base while maintaining the flexibility of custom pricing.
[Learn more](../guide/plans/overview#editing-plans)
## Sync billing data to HubSpot
With Lago’s new integration, you can now seamlessly sync billing data in real time to HubSpot. By connecting your Lago account to HubSpot, you’ll enable the following:
1. **Customer Creation**: Automatically create Contacts or Companies in HubSpot based on your Lago customer data.
2. **Invoice Syncing**: Real-time invoice sync to a HubSpot custom object named `LagoInvoices`.
3. **Subscription Syncing**: Real-time subscription sync to a HubSpot custom object named `LagoSubscriptions`.
[Learn more](../integrations/crm/hubspot)
## Quote in Salesforce CPQ, bill in Lago!
Our enhanced Salesforce package now enables you to use Salesforce CPQ for quoting leads and customers.
**Once a quote is approved and signed, it automatically triggers a real-time subscription in Lago**.
No need for separate processes—your sales team can directly create subscriptions from validated quotes within Salesforce.
[Learn more](../integrations/crm/salesforce-cpq)
## Dynamic pricing
Do your prices change dynamically based on a provider or complex in-house calculations?
Here are some real-life use cases:
* 🤖 AI companies: prices fluctuating based on real-time models cost
* 🏦 Fintech: matching prices to live market data
* 📱 Telco/CPaaS: adjusting costs to fluctuating carrier rates
We've heard you, and we're excited to introduce Dynamic Pricing for this!
You can now set a charge model as Dynamic and send the event amount directly through each event. No more headaches trying to manage interchange fees or fluctuating custom prices.
[Learn more](../guide/plans/charges/charge-models/dynamic)
## Credit note on prepaid credit invoices
Refund your customers who purchased prepaid credit in no time!
You can now process refunds for prepaid credit bought within Lago directly, without needing to engage your payment provider.
Lago takes care of the refund through its credit note module, enabling you to initiate the refund to the payment provider and automatically void the prepaid credit in the active wallet according to the wallet’s refund status.
[Learn more](/guide/credit-notes.mdx)
## Customer Portal complete rework
We’ve **completely reworked the Customer Portal**. You can now embed the portal URL to display in real-time **plans and usage information**, **wallet data**, **customer info**, and **invoice lists**.
Additionally, your end customers can take actions directly within the portal, such as **adding prepaid credits** and **updating their customer info**—all automatically synced with your Lago back office.
**Cherry on top?** We’re offering the new Customer Portal **for free** to all users, including those on our open-source plan.
## Usage ingestion sources
Premium ingestion sources for metering and usage consumption are now **generally available**.
Instead of using the basic API, you can leverage dedicated connectors to ingest data directly from sources like **AWS S3**, **AWS Kinesis**, **Kafka**, **MongoDB**, and **Azure**.
Most connectors support ingestion rates of **over 15,000 events per second** (compared to 1,000 via the basic REST API).
For custom ingestion connectors, please contact the Lago team.
[Learn more](/guide/events/metering-source)
## Customer type
Users can specify whether the customer is a company or an individual by setting the customer type.
By default, if no customer type is specified, customers are created without a defined type and you will need to assign one manually.
[Learn more](/guide/customers/customer-management#companies-vs-individuals)
## Send tax invoices
Lago invoices are now fully compliant with local legislation in Australia, Indonesia, New Zealand and the United Arab Emirates.
In those countries, it is mandatory to emit "Tax Invoices" accord to specific rules. This can now be handled with Lago.
## Retrieve all events using the API
Users can now retrieve and filters all events using the API. The endpoint also allows for filtering by:
* `code`
* `external_subscription_id`
* `timestamp_from`
* `timestamp_to`
[Learn more](/api-reference/events/list-events)
## Anrok integration ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
We have developed an integration with Anrok to make tax management easier. This native integration allows you to automatically update your invoices with tax amounts sourced directly from Anrok.
* Lago sends the customer's address, tax identifier (if applicable), and the relevant product ID to calculate the appropriate tax for each line item
* Anrok calculates the tax for the invoice and returns the data to Lago, which is used to update the invoice with accurate tax information
* Lago synchronizes updates for voided and disputed invoices, as well as any credit notes created, ensuring that your records remain up to date
This integration ensures compliance with international tax regulations by calculating taxes for US & non-US obligations, like VAT.
[Learn more](/integrations/taxes/anrok#mapping-items-between-lago-and-anrok-mandatory)
## Precise amount for fees
Lago now allows you to retrieve the precise (ie. non rounded) amount on the fee object. Before only the rounded `amount_cents` was available.
To use the precise fee amount, you can use the `precise_amount` field.
[Learn more](/api-reference/fees/fee-object)
## Progressive billing ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
Progressive billing, also known as threshold billing, automatically triggers an invoice when a customer's cumulative usage reaches predefined thresholds.
This method ensures that customers cannot exceed certain usage limits without ensuring payment is received, reducing the risk of unpaid services or fraud.
You can setup 2 types of threshold:
* Step-based threshold: invoices are generated when the lifetime usage of a subscription reaches a defined threshold. You can set an unlimited number of thresholds, each with a specific amount and a unique name
* Recurring threshold: this threshold determines what happens after the final step-based threshold is reached. (For example, after the last threshold, Lago will automatically bill \$100 each time the lifetime usage increments by that amount)
[Learn more](/guide/plans/progressive-billing#progressive-billing)
## Skip empty invoices generation
Users can now decide whether or not to issue \$0 invoices (ie. empty invoices). By default, empty invoices are generated. You can change this setting at the organisation level.
When creating a customer, it takes by default the configuration of the organization for this specific field.
However, you can decide to override this information for a specific customer. Why? You might have customers who need to receive an invoice each month, even if the total amount is 0.
[Learn more](/guide/invoicing/overview#finalize-empty-invoices)
## Filter and export invoices
Users can now filter the list of invoices (e.g. by currency, customer, issuing date, etc.) and the filtered list can then be exported from the user interface.
Two export options are available:
* Standard, including the list of invoices and invoice amounts (i.e. one row per invoice)
* Advanced, including the list of fees (i.e. one row per fee, so multiple rows per invoice if the invoice includes multiple fees)
The list is automatically emailed to the requester in a CSV file.
[Learn more](/guide/invoicing/export)
## Wallet transaction metadata
When creating a wallet transaction via API, you can add metadata to store additional information (e.g. source of the transaction).
This information is not displayed in the user interface.
[Learn more](/api-reference/wallets/wallet-transaction-object)
## Invoicing options for wallet top-ups
When creating a new wallet for a customer, users can choose to generate invoices for credit purchases either:
* As soon as the wallet transaction is created
* Only when payment is successful, which avoids generating invoices for transactions that have not been finalized
These options are also available for automatic and manual top-ups (see `wallet_transaction.invoice_requires_successful_payment`).
[Learn more](/guide/wallet-and-prepaid-credits/overview#invoicing-after-successful-payment-option)
## API changes (v1.7.0)
As announced a few months ago, we have updated the event ingestion process and removed deprecated API fields. Changes include:
**1. Replacing groups with filters**
The new dimension system based on filters allows users to create billable metrics with more than two dimensions, and makes it easier to create charges based on custom event properties. The old dimension system based on groups has been permanently removed from the Lago API ([see all changes](/guide/migration/migration-to-v1.2.0#1-transition-from-group-to-filters)).
**2. Marking `external_subscription_id` as mandatory for events**
Events that only include `external_customer_id` are no longer taken into account when aggregating usage ([learn more](/guide/migration/migration-to-v1.2.0#2-mandatory-external-subscription-id-field-in-event-payloads)). This change will streamline the event validation process and enable real-time billing capabilities.
**3. Removing deprecated API fields**
For the sake of clarity and to preserve the quality of the API, we've deprecated several legacy fields ([see full list](/guide/migration/migration-to-v1.2.0#3-deprecated-fields)).
[Learn more](/guide/migration/migration-to-v1.2.0)
## Invoicing options for instant charges ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
For charges paid in advances, Lago offers three invoicing options:
* An invoice can be issued for each event
* An invoice that only includes paid fees can be issued at the end of the billing period
* No invoices (users only rely on the `fee.created` webhook)
[Learn more](/guide/plans/charges/invoiceable-vs-noninvoiceable)
## Xero integration ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
We have developed a Xero integration to make accounting easier. Available features include:
* Connecting a Lago account to a Xero account via OAuth
* Mapping Lago objects such as billable metrics, plans, coupons, wallet credits and taxes to Xero items
* Real-time synchronization of customer accounts
* Real-time synchronization of invoices
* Real-time synchronization of credit notes
* Real-time synchronization of payments
[Learn more](/integrations/accounting/xero)
## Link checkout
For card payments processed through integration with Stripe, users can enable the Link option. Link automatically fills the customer's payment information for faster checkout.
[Learn more](/integrations/payments/stripe-integration#link)
## Overview of customer billing
The customer view features a new billing section, including:
* Gross revenue (i.e. total amount billed to the customer)
* Total overdue (i.e. total amount of invoices that are past their due date)
This improvement is the first step toward dunning management (coming soon).
[Learn more](/guide/customers/customer-management#monitor-the-customers-billing-status)
## NetSuite integration ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
We have developed a NetSuite integration to make accounting easier. Available features include:
* Connecting a Lago account to a NetSuite account via OAuth
* Mapping Lago objects such as billable metrics, plans, coupons, wallet credits and taxes to NetSuite items and tax items
* Real-time synchronization of customer accounts
* Real-time synchronization of invoices (and sales orders)
* Real-time synchronization of credit notes
* Real-time synchronization of payments
[Learn more](/integrations/accounting/netsuite)
## Shipping address
In addition to the customer's billing address, users can add a shipping address. This information can be useful when the applicable tax rates are determined through integration with a tax management provider (e.g. Anrok).
## Overdue invoices
If an invoice is not marked as paid once its due date has passed, it is considered to be overdue. The billing system will then send a webhook message to notify the organization that issued the invoice (see `invoice.payment_overdue`).
[Learn more](/api-reference/webhooks/messages#payment-overdue)
## Custom pricing ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
For companies whose aggregation and pricing models cannot be reproduced using standard functions, our team can inject a custom code snippet into the billing application.
This feature allows users to implement advanced billing rules based on custom logic, which can be very useful when migrating from an in-house billing system.
[Learn more](/guide/plans/charges/charge-models/custom-price)
## Okta SSO ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
Users can sign up and log in to their Lago account through Okta single sign-on (SSO), which enables a better experience and ensures that the identity provider remains the system of record for authenticating users.
[Learn more](/guide/security/sso#okta-sso)
## Hiding subscription fees at zero
We have modified the invoice template and introduced new rules for subscription fees:
* If `amount_cents` is zero for the subscription fee and there are no other fees (e.g. usage-based charges or commitment) in the invoice, the subscription fee will appear on the PDF invoice
* If `amount_cents` is zero for the subscription fee and there are other fees in the invoice, the subscription fee will not be displayed on the PDF invoice
## Role-based access control (RBAC) ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
With the RBAC feature, organizations can ensure that each member only has access to the information and actions required to perform their job duties.
There are three roles available on the Lago platform:
* Admin: full access to all views and actions (usually assigned to billing engineers and managers)
* Account Manager: can manage customer accounts and subscriptions (suitable for sales and success teams)
* Finance & Analyst: mostly view-only, with the ability to manage invoices and credit notes
[Learn more](/guide/security/rbac)
## Recurring wallet top-ups ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
Users can define rules to automatically trigger wallet top-ups, based on two methods:
* Fixed: a predefined number of credits is added to the customer's wallet
* Target: credits are added to the customer's wallet to reach a predefined balance
There are also two trigger options:
* Interval: weekly, monthly, quarterly or yearly top-ups, with a custom start date
* Threshold: the top-up is triggered when the ongoing balance of the wallet reaches a predefined minimum threshold
[Learn more](/guide/wallet-and-prepaid-credits/wallet-top-up-and-void#setup-recurring-top-ups)
## Webhook messages for wallets
Lago now sends webhook messages when:
* A wallet transaction is created (see `wallet_transaction.created`)
* The status of a wallet transaction is updated (e.g. when a pending transaction is settled - see `wallet_transaction.updated`)
* When the ongoing balance of the wallet is zero or less than zero (see `wallet.depleted_ongoing_balance`)
[Learn more](/api-reference/webhooks/messages#wallets)
## Void wallet credits
The endpoint `POST /wallet_transactions` includes a new function to void credits, which are immediately deducted from the balance of the customer's wallet.
This action can also be triggered via the user interface.
[Learn more](/api-reference/wallets/top-up)
## Filters for billable metrics
We have made changes to our dimension system and replaced metric groups with filters. This new feature offers greater flexibility as:
* Users can create as many filters as needed (they are no longer limited to two dimensions)
* Users can define specific rates based on very granular filter combinations (e.g. online card payments with Visa cards, offline card payments with Amex cards, etc.)
[Learn more](/guide/plans/charges/charges-with-filters)
## Google SSO
Users can sign up and log in to their Lago account through Google single sign-on (SSO), which enables a better experience and ensures that the identity provider remains the system of record for authenticating users.
[Learn more](/guide/security/sso#google-sso)
## Improved trial period
When the subscription fee of a plan is paid in advance and the plan includes a trial period, the first invoice was initially generated when the subscription started. Following feedback from the Lago Community, we have modified this logic to generate the first invoice at the end of the free trial.
[Learn more](/guide/plans/plan-model#the-trial-period-optional)
## Payment disputes
If a payment dispute is reported as lost by the payment provider, Lago will provide `invoice.payment_dispute_lost_at` and send the webhook message `invoice.payment_dispute_lost`.
This feature is available via integrations with Stripe and Adyen.
## Upcoming API changes (v1.2.0)
We have released a new version of Lago with exciting new features, but also API changes likely to affect our users' workflows.
**1. Replacing groups with filters**
We have developed a new dimension system that offers greater flexibility. Filters allow users to create billable metrics with more than two dimensions, and make it easier to create charges based on custom event properties.
However, this feature introduces changes to a number of objects, including `billable_metric`, `plan`, `fee` and `customer_usage`. In addition, the endpoint to retrieve billable metric groups will be deprecated ([see all changes](/guide/migration/migration-to-v1.2.0#1-transition-from-group-to-filters)).
**2. The external subscription ID becomes mandatory for events**
In order to develop real-time billing capabilities, we need to streamline our validation process. We have therefore decided to make `external_subscription_id` mandatory when sending events via the Lago API.
Events that only include `external_customer_id` will no longer be taken into account when aggregating usage ([learn more](/guide/migration/migration-to-v1.2.0#2-mandatory-external-subscription-id-field-in-event-payloads)).
**3. Deprecation of API fields**
For the sake of clarity and to preserve the quality of the API, we are going to deprecate several legacy fields ([see full list](/guide/migration/migration-to-v1.2.0#3-deprecated-fields)).
**Timeline**
We will maintain the current API logic until July 9, 2024. After this date, previous versions will no longer be supported. We kindly ask our users to update their integration before that day to avoid any potential breaking change.
[Learn more](/guide/migration/migration-to-v1.2.0)
## Minimum plan commitment ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
When creating a plan, defining a commitment ensures a minimum invoice amount for the billing period.
This minimum is calculated at the end of the period, taking into account the subscription fee and all usage-based charges. If the total amount invoiced is less than the minimum commitment, Lago will automatically apply a true-up fee.
The default commitment can be overridden when assigning the plan to a customer.
[Learn more](/guide/plans/commitment)
## ACH and BACS payments
Lago's native integration with Stripe supports two new payment methods:
* ACH Direct Debit for customers with a US bank account
* BACS Direct Debit for customers with a UK bank account
[Learn more](/integrations/payments/stripe-integration#supported-payment-methods)
## Grouping of charges
It is possible to group charges on the invoice according to a custom attribute. When creating a charge based on the standard pricing model, users can define one or several `grouped_by` attributes that will then be used to provide information on the distribution of usage.
For a customer who has sent thousands of API requests, for instance, we could display the breakdown of usage based on the `workspace_id` to which each request is linked.
[Learn more](/guide/invoicing/overview#custom-invoice-grouping)
## Updated Salesforce package ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to the Salesforce CRM integration.
This new package allows users to initiate actions in Lago without leaving the Salesforce interface. It includes two customizable flows:
1. Ability to automatically create Lago customers from Salesforce accounts
2. Ability to automatically create Lago subscriptions from Salesforce opportunities, including the option to override existing plans
[Learn more](/integrations/crm/salesforce-crm#iii-actions-from-salesforce-to-lago)
## Payment link for a specific invoice
We have added a new endpoint to generate checkout URLs for specific invoices.
This feature is available via integrations with Stripe and Adyen. It allows users to collect payments in countries where payment methods cannot be saved for future use.
[Learn more](/api-reference/invoices/payment-url)
## Wallet balance in (near) real-time ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
In addition to the invoiced balance, which represents the credit available in the wallet after the last invoice has been finalized, wallets include an ongoing balance, which takes into account the customer's current usage and taxes.
The ongoing balance gives an overview of the credit available in the wallet in near real-time, as it is updated every 5 minutes.
[Learn more](/guide/wallet-and-prepaid-credits/overview#real-time-wallet-balance)
## Edit draft invoices ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
When an invoice is in draft (i.e. during the grace period), fees can be modified via the user interface. Users can either:
* Overwrite the total number of units, in which case Lago will automatically recalculate the fee based on the pricing model associated with the charge
* Overwrite the number of units and unit price, in which case Lago will automatically recalculate the fee based on this information
[Learn more](/guide/invoicing/grace-period#edit-a-specific-fee)
## Multiple PSP accounts
If an organization has multiple accounts with the same PSP (e.g. US Stripe account and EU Stripe account) they can all be connected to Lago. Users can then select the most appropriate account to process payments for each customer.
[Learn more](/integrations/introduction#payments-integrations)
## Batch endpoint
Events can now be sent in batches using the new `/events/batch` endpoint. Each API call may include up to 100 events.
[Learn more](/api-reference/events/batch)
## Disabling emails for invoices without fees
To avoid sending too many notifications to customers, we have deactivated emails for invoices without fees.
Although invoices with `"fees_amount_cents": 0` are no longer sent to customers by email, they are still available in the database and user interface.
[Learn more](/guide/emails#email-scenarios)
## Custom invoice numbering
We have made invoice numbering more flexible, with three elements:
* Prefix that can be customized
* Dynamic sequence, either based on sequential customer IDs, or based on year and month (i.e. YYYYMM)
* Sequential number of the invoice (i.e. 001, 002, 003, etc.)
[Learn more](/guide/invoicing/overview#invoice-numbering)
## EU tax management
Lago's EU tax detection feature allows users to check customers' tax identification numbers through integration with the European VAT Information Exchange System (VIES), and to automatically assign them a tax rate based on their country.
[Learn more](/integrations/taxes/lago-eu-taxes)
## Unit prices
PDF invoices now include details of charges for each pricing model (e.g. for graduated pricing, we display the number of units and unit price for each tier).
This information is also available in the invoice object (see `invoice.fees.amount_details`).
[Learn more](/api-reference/invoices/invoice-object)
## Automatic wallet top-ups ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
Customer wallets can be topped up automatically according to predefined rules:
* Based on a time interval (e.g. weekly, monthly, etc.)
* Based on a threshold (e.g. when the wallet balance is less than or equal to \$10)
[Learn more](/guide/wallet-and-prepaid-credits/wallet-top-up-and-void#setup-recurring-top-ups)
## Event validations
We have added an `events.errors` webhook message to notify users when some of the events ingested in the last hour are invalid.
Possible errors include:
* Invalid billable metric code
* Missing aggregation property
* Missing group key
[Learn more](/api-reference/webhooks/messages#event-ingestion)
## Regenerate checkout links
When a customer wants to update their payment method, or when a checkout link has expired, users can generate a new checkout URL on demand through the Lago API.
This action is available for all our native payment integrations.
[Learn more](/api-reference/customers/psp-checkout-url)
## Custom success URL
When setting up one of our native payment integrations, users can define the URL to which customers should be redirected after completing the checkout process. Custom URLs can only be added via the user interface.
[Learn more](/integrations/introduction#payments-integrations)
## Default currency
The organization's currency can be defined in the settings of the account or via API. It is used as the default currency when creating new objects, such as plans and add-ons, and to display information on dashboards.
[Learn more](/api-reference/organizations/update)
## Helm chart updates
We have released a new version of the Lago Helm Charts to facilitate on-premise deployment.
[Learn more](https://github.com/getlago/lago-helm-charts)
## Integration with Salesforce CRM ✨
✨ This feature is only available via a paying add-on. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to the Salesforce CRM integration.
With the new Salesforce CRM integration, Lago data is automatically synced with Salesforce.
Users can access their customers' subscriptions, invoices and credit notes directly in their CRM application.
[Learn more](/integrations/crm/salesforce-crm)
## Removal of event validations
We are currently upgrading our infrastructure and setting up a new event ingestion system. As part of this project, we have decided to remove the validations that were automatically performed when ingesting events through the Lago API.
This means that the API no longer returns error messages when events include incorrect parameters (e.g. wrong billable metric code, subscription not found, `transaction_id` already exists, etc.).
## Retrieve a subscription
We have added a new endpoint to allow users to retrieve a specific subscription via the Lago API, using the `external_id` of the subscription.
[Learn more](/api-reference/subscriptions/get-specific)
## Webhooks for subscription upgrades/downgrades
When the plan associated with a subscription changes, Lago automatically notifies the user with two webhook messages:
* `subscription.terminated` to confirm the termination of the initial plan (includes `next_plan_code`)
* `subscription.started` to confirm the start of the new plan (includes `previous_plan_code`)
[Learn more](/api-reference/webhooks/messages)
## Plan details
In the Plans section of the app, users can now click one of their plans to see its details (i.e. name, code, interval, currency, subscription fee, usage-based charges, etc.) and also retrieve the list of subscriptions linked to the plan.
In addition, in the customer view of the app, users can click one of the subscriptions assigned to their customer to see its details (i.e. status, start date, interval, currency, fees, charges, etc.).
## Override plans ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
When assigning a plan to a customer, you can modify some attributes to create a custom plan. Editable fields include (but are not limited to):
* Currency
* Subscription fee
* Charge prices
* Minimum spending requirements
* Tax rates
* Invoice display names
Details of the new plan will be available in the customer view.
[Learn more](/guide/subscriptions/assign-plan#overriding-a-plan)
## Spanish locale
¡Hola a todos! The Spanish locale is now available on Lago.
Users can select it as their organization's default language or as a customer's preferred language.
[Learn more](/api-reference/resources/locales)
## Swedish locale
Hej alla! The Swedish locale is now available on Lago.
Users can select it as their organization's default language or as a customer's preferred language.
[Learn more](/api-reference/resources/locales)
## Display names on invoices
When creating or updating a plan, users can define custom display names for subscription and usage-based charges, which will be printed on the PDF files generated by Lago.
Display names can be defined via the user interface or the API (see `plan.invoice_display_name` and `charges.invoice_display_name`).
[Learn more](/guide/plans/charges/overview#update-invoice-display-names)
## Retrieve past usage
We have added a new endpoint to retrieve past usage. When a billing period has ended, users can still retrieve usage data through `GET /customers/{external_customer_id}/past_usage`.
Users must specify `external_subscription_id` and can filter results by `billable_metric_code`. They can also select the number of past periods for which they wish to retrieve usage data.
[Learn more](/api-reference/customer-usage/get-past)
## LATEST aggregation
`latest_agg` allows users to compute usage based on the last value received during the period for a billable metric.
Consider the following example for the `storage` metric, where usage is aggregated based on the property `gb`:
* The first event includes 5 GB
* The second event includes 7 GB
* The third event includes 6 GB
With `latest_agg`, at the end of the billing period, the total number of units used to calculate the fee will be 6, as it's the last value received.
[Learn more](/guide/billable-metrics/aggregation-types/latest)
## WEIGHTED SUM aggregation
`weighted_sum_agg` allows users to compute usage based on a custom property and the time elapsed between two events (e.g. memory consumption measured in GB-seconds).
Billable metrics based on this aggregation type can be metered or recurring, and are always billed at the end of the billing period.
[Learn more](/guide/billable-metrics/aggregation-types/weighted-sum)
## Subscription end date
When a subscription end date is set, the subscription is automatically terminated by Lago.
A notification is sent to the user 45 days and 15 days before the subscription is terminated (see `subscription.termination_alert` webhook).
If no end date is set for a subscription, it will renew automatically.
[Learn more](/guide/subscriptions/assign-plan#subscription-end-date)
## Duplicate plans
Users can duplicate an existing plan from the user interface to create a new plan with the same structure. They can then choose a name and a code for their new plan, and modify the parameters that differ from the original plan (e.g. interval, currency, charges, etc.).
## Edit dimensions
When dimensions are defined for a billable metric, users can add/remove groups by modifying the corresponding code snippet via the user interface, or by updating the billable metric object via API.
Changes to dimensions may affect all plans where the billable metric is listed as a charge.
[Learn more](/guide/billable-metrics/filters)
## Default price for groups
For billable metrics that include several [groups](/guide/billable-metrics/filters), when configuring their plans, users can set a default price that applies to all groups.
The default price can be overwritten by setting a different price for a specific group.
If the default price is not defined, it is automatically set to zero.
[Learn more](/guide/invoicing/overview#custom-invoice-grouping)
## Italian locale
Ciao a tutti! The Italian locale is now available on Lago.
Users can select it as their organization's default language or as a customer's preferred language.
[Learn more](/api-reference/resources/locales)
## Minimum / Maximum per transaction ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
The percentage pricing model includes a new option for defining minimum and maximum prices per transaction.
When applied, Lago adjusts the fees based on the `per_transaction_min_amount` and `per_transaction_max_amount` parameters.
[Learn more](/guide/plans/charges#available-charge-models)
## Webhook for subscriptions started
We have added a new webhook message for subscriptions.
When the status of a subscription switches to `active`, Lago automatically sends a `subscription.started` message.
[Learn more](/api-reference/webhooks/messages)
## Graduated percentage pricing
We have added a new graduated pricing model, which allows users to define prices based on a percentage of the number of units, and to add a flat fee for each tier (optional).
[Learn more](/guide/plans/charges#available-charge-models)
## Quarterly billing interval
In addition to the weekly, monthly and yearly intervals, Lago `v0.44.1-beta` includes the new quarterly interval.
When selected, all fees (i.e. subscription fee and charges) are billed every three months.
[Learn more](/guide/plans/plan-model#plan-interval)
## Webhook signatures
When creating a webhook endpoint through the user interface or the API, you can choose between:
* The original `JWT` signature
* The new `HMAC` signature, which includes a shorter header
Please refer to the guide to find out how to verify the webhook signatures.
[Learn more](/api-reference/webhooks/format---signature)
## Taxes applied to add-ons
Tax objects can now be used to define the default tax rate(s) associated with an add-on.
When creating a one-off invoice, if there is no tax rate associated with the add-on, Lago will automatically select the tax rate defined at customer or organization level.
The tax rate applied to the add-on can be modified at any time through the user interface or the API.
[Learn more](/guide/invoicing/taxes#taxes-at-the-add-on-level)
## Net payment term
The net payment term determines the number of days given to the customer to pay their invoice. It is calculated based on the date the invoice is finalized and displayed on the PDF file.
When the net payment term is defined at the organization level, it applies to all customers by default. However, it can be overridden by the net payment term defined at the customer level.
[Learn more](/guide/invoicing/net-payment-term)
## Taxes defined at plan and charge level
In addition to the taxes defined at organization and customer level, users can select tax objects at plan and charge level.
For subscription invoices, the tax hierarchy is as follows:
1. Taxes defined at **organization level** will apply to all fees (i.e. subscription and charges)
2. Taxes defined at **customer level** will take precedence over taxes defined at organization level and will apply to all fees (i.e. subscription and charges)
3. Taxes defined at **plan level** will take precedence over taxes defined at customer level and will apply to all fees (i.e. subscription and charges)
4. Taxes defined at **charge level** will take precedence over taxes defined at plan level but will only apply to the fee associated with the corresponding charge
[Learn more](/guide/invoicing/taxes)
## Filter subscriptions by status
We have added a new query parameter to the endpoint that allows users to retrieve subscriptions.
By default, `GET /api/v1/subscriptions/` returns all active subscriptions. However, you can also retrieve pending, canceled and terminated subscriptions by using the `status` parameter.
[Learn more](/api-reference/subscriptions/get-all)
## SEPA Direct Debit with Stripe
Our native integration with Stripe now supports SEPA Direct Debit payments.
When Stripe is defined as the default payment provider for a customer, you can select the authorised payment method(s): card, direct debit or both.
Before initiating a payment intent, Lago will automatically check the customer's default payment method registered in Stripe.
Kindly note, SEPA Direct Debit is only available for invoices denominated in euros (EUR).
[Learn more](/integrations/payments/stripe-integration#payment-methods)
## Recurring and prorated charges
When a billable metric is defined as [recurring](/guide/plans/charges#metered-vs-recurring-charges), the number of billing units at the end of the billing period is carried over to the next period. It is not reset to zero, as with metered metrics.
Users can create recurring metrics based on `sum_agg` and `count_unique_agg`. They can also define whether the corresponding charges should be [prorated](/guide/plans/charges#prorated-vs-fully-billed-charges) (this option is only available for the standard and volume pricing models).
ℹ️ Metrics based on `recurring_count_agg` have been automatically converted into `count_unique_agg` metrics with the attribute `"recurring": true`.
## Cancel pending subscriptions
When a subscription is created with a subscription date in the future, its status is automatically set to `pending`.
You can now cancel a pending subscription through the Lago API, using the following endpoint:
`DELETE /api/v1/subscriptions/{external_id}?status=pending`
[Learn more](/api-reference/subscriptions/terminate)
## Multiple webhook endpoints
Webhook messages can be used to collect billing information and set up custom workflows. They are related to subscriptions, events, fees, invoices, payment providers and credit notes.
You can now create up to five webhook endpoints to listen to Lago events.
[Learn more](/guide/webhooks)
## Custom tax objects
In the settings of their account, users can define the default tax rate that applies by default to all customers of their organization. This tax rate can then be overwritten at the customer level.
Whether set at the organization level or the customer level, so far the tax rate used to calculate fees was simply indicated as "Tax" on invoices.
To give users more flexibility, we've added the option to create several tax objects, which can then be assigned to the organization or specific customers (e.g. state sales tax, VAT, reverse charge, GST, etc.).
[Learn more](/guide/invoicing/taxes)
## Stripe checkout URL
When a new customer is successfully created through Lago's native integration with Stripe, the billing system sends a `customer.checkout_url_generated` webhook message.
You can redirect your customer to the corresponding page to register their payment method, which will then be used to collect payment when a new invoice is issued.
[Learn more](/integrations/payments/stripe-integration#stripe-checkout-storing-customers-payment-method-information)
## Tax identification number
The [customer object](/api-reference/customers/object) and [organization object](/api-reference/organizations/organization-object) include a new `tax_identification_number` attribute. When a value is available for this attribute, it is automatically displayed on the PDF version of the next invoices.
## Integration with GoCardless
Lago now offers native integration with [GoCardless](https://gocardless.com/), including (but not limited to):
* Ability to define GoCardless as the default payment provider for a customer
* Ability to automatically create Lago customers in GoCardless and retrieve their customer ID
* Ability to automatically collect payments via direct debit
* Ability to automatically update the status of an invoice depending on the payment status
* Ability to automatically resubmit failed payments with [GoCardless Success+](https://gocardless.com/solutions/success-plus/)
To learn more about this integration, please [consult our guide](/integrations/payments/gocardless-integration)
## Minimum spend on charges ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
You can now define minimum spending requirements for usage-based charges.
The minimum spend is defined as an amount excluding tax. If at the end of the billing period, your customer has spent less than the minimum, then Lago will automatically generate a true-up fee to compensate for the difference.
Minimum spending requirements are defined when creating or editing plans, either through the user interface or the API.
[Learn more](/guide/plans/charges#charge-spending-minimum)
## Coupons limited to specific metrics
We have added a new option to the coupon settings: it is now possible to limit the application scope of a coupon to specific billable metrics.
By default, coupons apply to all charges but when creating a new coupon, you can define the list of billable metrics to which the coupon applies.
This feature is related to the `billable_metric_codes` attribute of the `coupon` object ([see API documentation](/api-reference/coupons/create)).
Please refer to [the guide](/guide/coupons) for more information on coupons.
## Reset password
You can now reset your password via the user interface.
On the login page, click "Forgotten password" to access the dedicated page where you can request a link to reset your password.
## Automatic emails ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
We are introducing a new built-in invoicing feature, which allows you to automatically send invoices and credit notes from Lago to your customers.
The email template can be customized with the name, email address and logo of your organization, and will be sent in the customer's preferred language (or the default language defined in the settings of your account).
For cloud users, Lago takes care of the SMTP setup. For users on the self-hosted version, the setup is described in the public documentation.
[Learn more](/guide/emails)
## Customer billing portal ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
We have released the first version of our billing portal, which allows your customers to access their invoices.
You can generate access links through the user interface or embed the customer portal into your application using our API and an iframe.
[Learn more](/guide/customers/customer-portal)
## Invoice metadata
After an invoice has been generated, you can add metadata to store additional information (e.g. custom ID, payment reference, etc.). This information will be included in the `invoice` object but will not be displayed on the PDF invoice.
Invoice metadata can be managed via the user interface or the API.
[Learn more](/guide/invoicing/invoice-metadata)
## Customer metadata
When creating or editing a customer, you can add metadata to store additional information (e.g. customer type, name of the account manager, etc.).
Customer metadata can be displayed on invoices, and can be managed via the user interface or the API.
[Learn more](/guide/customers/customer-metadata)
## Webhook logs
The new webhook management system allows you to access the list of webhook messages sent by Lago and check their status. You can re-trigger a message that has failed through the user interface.
To access the webhook logs:
1. Go to the **Developers** section via the sidebar
2. Open the **Webhooks** tab
3. Click on the webhook endpoint to see the list of messages
[Learn more](/guide/webhooks)
## Document translation
PDF files including invoices and credit notes can be generated in different languages.
The [default language](/guide/invoicing/download-invoices#translate-invoices) that is set at the organization level can be overwritten by the [customer's preferred language](/guide/customers/invoice-customer#preferred-language).
In the API, the `document_locale` attribute determines the language of the documents.
You can contribute to Lago's open-source project by helping us translate documents. The new language will then be added to the [list of supported locales](/api-reference/resources/locales) and available to the entire Lago Community.
## Update payment status
You can now update the payment status of an invoice through the user interface.
To do so:
1. Access the **Invoices** section
2. Find the relevant invoice
3. Click the ellipsis icon on the right
4. Click **Update payment status**
5. Select the new payment status
6. Click **Update status** to confirm
This action can be performed [via the API](/api-reference/invoices/update) as well.
## Coupons limited to specific plans
We have added a new option to the coupon settings: it is now possible to limit the application scope of a coupon to specific plans.
By default, coupons apply to all plans but when creating a new coupon, you can define the list of plans to which the coupon applies.
This feature is related to the `plan_codes` attribute of the `coupon` object ([see API documentation](/api-reference/coupons/create)).
Please refer to [the guide](/guide/coupons) for more information on coupons.
## Coupons that apply forever
When creating a coupon, through the [user interface](/guide/coupons) or the [API](/api-reference/coupons/create), it is now possible to select the `forever` frequency.
Coupons with the `forever` frequency apply to all subscription invoices, regardless of the number of subscription invoices generated in a given period.
ℹ️ The value of the coupon is deducted from the amount of the invoice after tax. Coupons do not apply to add-ons or any other one-off charges.
## Search bar
Tired of scrolling through an endless list to find the customer your are looking for? We understand that.
We have added a search functionality to the user interface to make it easier to find metrics, plans, customers, invoices, etc.
## Payment retries
We have added the ability to resend payments for collection.
This new feature is available to all users:
* Through the user interface ([learn more](/guide/payments/payment-retries))
* Through the API ([learn more](/guide/payments/payment-retries))
## Grace period ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
If at the end of the billing period, you want to review the invoices before sending them to customers for payment, you can define a [grace period](/guide/invoicing/grace-period).
During the grace period, invoices are in `draft` status and can be modified. Available actions include:
* **Adding usage records** by sending events with a `timestamp` within the relevant billing period
* **Applying coupons** to the customer's account
* **Adding credits** to the customer's wallet and credit note wallet
When the grace period expires, invoices are automatically `finalized` (they can no longer be edited), which triggers the `invoice.created` [webhook](/api-reference/webhooks/messages). You can also finalize invoices manually.
The organization's grace period applies to all customers by default, but it can be overwritten by the customer's grace period.
## Invoice list
We have added a new **Invoices** section, which allows you to access the list of invoices.
Invoices are filtered according to their status (i.e. draft or finalized) and according to their payment status (i.e. succeeded, pending or failed).
The same filters can be applied when [retrieving invoices via the API](/api-reference/invoices/get-all).
## Credit notes ✨
✨ Lago may automatically generate a credit note when a subscription is upgraded or downgraded. However, only users with a premium license can manually generate credit notes via the user interface or the API. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
You can now use your Lago account to issue credit notes for subscription invoices and add-ons.
Depending on the payment status of the invoice, you will be able to:
* **Refund the customer** (only for paid invoices)
* **Credit back the customer's account**
Please refer to the [documentation](/guide/credit-notes) for more information on credit notes and credit methods.
## Timezones ✨
✨ This feature is only available to users with a premium license. Please contact [hello@getlago.com](mailto:hello@getlago.com) to get access to Lago Cloud and Lago Self-Hosted Premium.
You can now set the timezone of your organization in the settings of the app. To do so:
1. Access the **Settings** section via the side menu
2. In the **Organization** tab, you will see the current timezone (UTC by default)
3. Click **Edit**
4. Select a new timezone from the list
5. Click **Save timezone** to confirm
It can also be set through the API using this [endpoint](/api-reference/organizations/update).
The organization's timezone applies to all customers by default and determines when billing periods start and end (i.e. when invoices should be generated). It is also the reference timezone for most views and lists in the app.
The organization's timezone can be overwritten by the customer's timezone ([learn more](/guide/customers/invoice-customer#bill-following-your-customers-timezone)).
ℹ️ In the app, you can hover over any date with a dotted underline to see the reference timezones.
## Lago Open API
We have developed an Open API to help you get started with Lago and make it easier to test our solution.
Please refer to the [documentation](/guide/lago-open-api) to learn how to import the Lago Open API into Postman and create a new collection.
Our [public repository](https://github.com/getlago/lago-openapi) is also available on GitHub.
## Apply several coupons
You can now apply several coupons to a customer account.
When several coupons are applied to a customer, they will be deducted according to the date on which they were applied: the coupon that was applied first will be deducted first.
The remaining value / number of remaining periods for each coupon will be visible in the **Overview** tab of the customer view.
You can also use `GET /api/v1/applied_coupons` to retrieve all coupons applied to a customer.
## Invoice details
To review the invoice details through the user interface:
1. Go to the **Customers** section
2. Select a customer to open the customer view
3. Open the **Invoices** tab
4. Click the invoice to see its details
On the details page, you can download the invoice in PDF format and copy the invoice ID through the **Actions** dropdown in the upper right corner.
## Integration with GoCardless
Lago now offers native integration with [GoCardless](https://gocardless.com/), including (but not limited to):
* Ability to define GoCardless as the default payment provider for a customer
* Ability to automatically create Lago customers in GoCardless and retrieve their customer ID
* Ability to automatically collect payments via direct debit
* Ability to automatically update the status of an invoice depending on the payment status
* Ability to automatically resubmit failed payments with [GoCardless Success+](https://gocardless.com/solutions/success-plus/)
To learn more about this integration, please [consult our guide](/integrations/payments/gocardless-integration).
## Subscription date
It is now possible to set a start date in the past or in the future for a new subscription.
Setting a start date in the past can be useful when migrating existing customers to Lago, while setting a start date in the future can be useful for scheduling upcoming subscriptions.
For more information about the impact of the start date on the invoicing process, please refer to [the documentation](/guide/subscriptions/assign-plan#subscription-date).
## Dimensions for grouping events
When creating a new billable metric, you can define dimensions that will be used to group events according to their properties.
For example, if you want to charge your customers for compute capacity according to the cloud provider and server region, you can create a `compute` billable metric with two dimensions ([learn more](/guide/billable-metrics/filters)).
Changes to the API include:
* Ability to add a `group` parameter with one or two dimensions when [creating](/api-reference/billable-metrics/create) or [updating](/api-reference/billable-metrics/update) billable metrics
* Ability to [retrieve the groups](/api-reference/billable-metrics/get-all-groups) associated with a billable metric
* Ability to add a `group_properties` parameter when [creating](/api-reference/plans/create) or [updating](/api-reference/plans/update) a plan
* Ability to retrieve [customer usage](/api-reference/customer-usage/customer-usage-object) by group
* New `lago_group_id` for fees (see [invoice object](/api-reference/invoices/invoice-object))
## Enhanced coupon model
We have improved the coupon model to offer more flexibility.
Changes include (but are not limited to):
1. Ability to define the value of a coupon as a fixed amount or percentage
2. Ability to create recurring coupons that apply over several billing periods
3. Ability to set an expiration date (i.e. date after which the coupon can no longer be redeemed)
[Learn more](/guide/coupons)
## Customer currency
It is now possible to define the currency at [customer](/api-reference/customers/object) level.
The currency associated with each customer was previously defined by the currency of the plan assigned to the customer. This logic prevented users from assigning a coupon or an add-on to a customer before creating a subscription.
When creating a new customer via the user interface or the API, you can now select the currency associated with the customer. If the currency is not defined at customer level, it will be determined by the first object assigned to the customer (i.e. currency of the plan, add-on, coupon, or wallet).
⚠️ Once an object has been assigned to the customer (i.e. plan, add-on, coupon, or wallet), the currency associated with the customer cannot be changed.
## Error management
We have refactored the error management system to give more visibility to API users.
The `message` attribute for errors has been replaced with `code` and `error_details`, which provide more information about the errors. There are several codes associated with each error.
For example, when creating a new billable metric, the API may return `"error": "Unprocessable entity"` with the code `value_is_mandatory` for the `name` field (i.e. the name of the billable metric is missing).
Please refer to the [documentation](/api-reference/intro) available for each endpoint for more information on error codes.
## Invite members
You can now invite your teammates to join your Lago account.
To add a new member via the user interface:
1. Go to the **Settings** section of the app
2. Open the **Members** tab
3. Click **Invite a member** on the right
4. Enter the email address of your teammate
5. Click **Generate invitation link** to confirm
6. Copy the invitation link to share it with your teammate
Invitation links have no expiration date. When your teammate clicks the link, they can choose their password and then access the account.
You can remove a member by clicking the **bin icon** on the right of the list of members.
ℹ️ All members have the same role and permissions.
## Overwrite plans
If after a negotiation phase, you need to create a custom plan for an important customer, you can use the 'overwrite' feature, available through the user interface.
This feature allows you to create a new plan from an existing one, in order to adjust the plan model and charges according to your business needs.
Overwriting a plan has no impact on the original plan or existing subscriptions.
[Learn more](/guide/subscriptions/assign-plan#overwriting-a-plan)
## Recurring count
Companies with fair and transparent pricing models are often praised by customers. If you are considering implementing seat-based pricing for instance, the `reccuring_count` aggregation is exactly what you need.
This new aggregation type allows you to push events for persistent units.
Consider the following example:
> Your customer is on a monthly plan and adds a new user to their account on September 15th, so you generate an event that corresponds to one billing unit.
>
> At the end of September, Lago will automatically create a prorated charge for this user, based on the number of days of activity (i.e. from September 15th to September 30th).
>
> This billing unit will remain valid until you generate another event to remove it. For instance, if your customer deletes the user on October 22nd, Lago will create another prorated charge for the period October 1st to October 22nd.
Consult [our guide](/guide/billable-metrics/recurring-vs-metered) to learn more about persistent units.
## External IDs
We are introducing changes to the API that will make it easier to manage subscriptions:
* For the [creation of new subscriptions](/api-reference/subscriptions/assign-plan), `subscription_id` and `unique_id` will be removed and replaced with `external_id` (required)
* For all other endpoints, `subscription_id` will be replaced with `external_subscription_id`
This will allow you to operate via the API using your own identifiers and save you the trouble for storing our IDs.
In addition to this, for consistency purposes:
* For the [creation of new customers](/api-reference/customers/create), `customer_id` will be replaced with `external_id`
* For all other endpoints, `customer_id will be replaced with `external\_customer\_id\`
These changes will come into effect on **September 8, 2022**.
Please [get in touch](https://www.getlago.com/slack) with our team if you have any questions.
## Volume charge model
The new volume charge model allows you to create a tiered pricing structure and then calculate a unit price that applies to all units depending on total volume.
It is similar to the graduated charge model, except that only one price tier applies at the end of the billing period.
Please refer to [the guide](/guide/plans/charges#charge-models) and [API documentation](/api-reference/plans/create) for more information.
## Anniversary dates for subscriptions
When assigning a plan to a customer, you can now choose whether the subscription should be renewed at the beginning of the period or on its anniversary date.
For instance, if a monthly plan is assigned to a customer on August 10th and you choose to align the billing cycle with the anniversary date of the subscription, the customer will be billed every 10th of the month.
With [the API](/api-reference/subscriptions/assign-plan), you can use the `billing_time` attribute to choose your preferred option. If not provided, Lago will base the subscription on calendar periods.
[Learn more](/guide/subscriptions/assign-plan#billing-cycles)
## Free units for the percentage charge model
We have released an enhanced version of the percentage charge model, including:
* Ability to define free units based on the number of events (e.g. first 3 events are free)
* Ability to define free units based on the total amount (e.g. first \$500 are free)
Please refer to the [documentation](/guide/plans/charges#charge-models) for more information.
## Multiple plans
It is now possible to assign multiple plans to a customer (e.g. if your customer needs to create several workspaces on your platform, you can link a plan to each workspace).
To help differentiate each plan, you can add display names that will appear in the user interface and on invoices.
Kindly note that:
1. All plans must be denominated in the same currency
2. You must now specify the `subscription_id` for each event or create batch events
[Click here to see the documentation](/guide/subscriptions/assign-plan#multiple-plans)
## Tracking & Analytics
To help us better understand your needs, we have added a tracking module to the self-hosted version of Lago.
Data analytics will help us improve the quality of our product and performance of the API.
As the privacy of our users is of paramount importance, we will not collect any personal information about your customers or the amount of your invoices, and you can opt out at any time.
[Learn more](/guide/self-hosted/tracking-analytics)
## Go client
We have added a new API client to make it easier for Go users to set up their billing system with Lago.
[Click here to see the documentation](/api-reference/intro)
## App version
It is now possible to check the version of the Lago application you are using.
Click on of your `organization's name` in the top-left corner of the user interface to see the app version currently in use.
## Current usage
Good news for those who follow closely the consumption of their customers. You can now track the current billing usage of your customers either from the UI or from the API.
**To access this Usage tab:**
1. Access your list of **customers**
2. Select a specific customer that is **already linked to a subscription**
3. Access the **usage** tab
4. Get a complete view of **usage-based consumption** that is going to be billed on the next invoice
On top of that, you can fetch the current usage of a customer directly from the API. To do so, you can access the following endpoint `GET /api/v1/customers/:customer_id/current_usage`
## PDF invoices
Lago will generate a PDF file for each new invoice.
You can download invoices via the user interface or the API and can also modify some of the elements included in the invoice template.
Full documentation [available here](/guide/invoicing/download-invoices).
## New API endpoints
We like our users when they use our nice and clean UI, but we also love when they use our API. One of the usecase could be to use Lago as a white-labeled solution.
Here is the full list of endpoints we have just released:
**Billable metrics**
* Create a billable metric `POST /api/v1/billable_metrics`
* Update a billable metric `PUT /api/v1/billable_metrics/:code`
* Destroy a billable metric `DELETE /api/v1/billable_metrics/:code`
* Fetch a specific billable metric `GET /api/v1/billable_metrics/:code`
* Fetch all billable metrics `GET /api/v1/billable_metrics?per_page=2&page=1`
**Plans**
* Create a plan `POST /api/v1/plans`
* Update a plan `PUT /api/v1/plans/:code`
* Destroy a plan `DELETE /api/v1/plans/:code`
* Fetch a specific plan `GET /api/v1/plans/:code`
* Fetch all plans `GET /api/v1/plans?per_page=2&page=1`
**Coupons**
* Create a coupon `POST /api/v1/coupons`
* Update a coupon `PUT /api/v1/coupons/:code`
* Destroy a coupon `DELETE /api/v1/coupons/:code`
* Fetch a specific coupon `GET /api/v1/coupons/:code`
* Fetch all coupons `GET /api/v1/coupons?per_page=2&page=1`
**Add-ons**
* Create a add\_on `POST /api/v1/add_ons`
* Update a add\_on `PUT /api/v1/add_ons/:code`
* Destroy a add\_on `DELETE /api/v1/add_ons/:code`
* Fetch a specific add\_on `GET /api/v1/add_ons/:code`
* Fetch all add\_ons `GET /api/v1/add_ons?per_page=2&page=1`
**Current usage**
* Get the current usage of a specific customer `GET /api/v1/customers/:customer_id/current_usage`
**Organization**
* Update the information of your organization `PUT /api/v1/organizations`
## Integration with Stripe Payments
Lago now offers native integration with Stripe, including (but not limited to):
* Ability to create Lago customers in Stripe automatically and retrieve their customer ID
* Ability to define Stripe as the default payment provider for a customer
* Ability to generate payment intents automatically
* Ability to update the status of an invoice depending on the payment status
* Ability to receive a webhook when a payment fails
To learn more about this integration, please [consult our guide](/integrations/payments/stripe-integration).
## Weekly plan interval
When setting up a plan, you can select the weekly interval to define a weekly billing period.
The plan interval applies to the subscription and charges, which means that:
* For plans that must be paid in advance, the subscription fee is invoiced at the beginning of the week
* For plans that are paid in arrears, the subscription fee is invoiced at the end of the week
* Usage is calculated at the end of each week
The week starts on Monday and ends on Sunday. If the customer's subscription starts in the middle of the week, the fees will be applied on a pro-rata basis.
## Invoice monthly charges for a plan paid yearly
Before the release of this feature, usaged-based features (charges) were following the plan period. If the plan period was invoiced yearly, the charges were invoiced yearly.
It's now possible to **invoice billable metrics on a montly basis** for a plan billed yearly. The base amount of the plan will be invoice yearly (in-arrears or in-advance), but your usage based features will be invoiced on a monthly basis.
**To do so:**
1. Access a **Plan**
2. Define a plan **yearly**
3. Price **additional charges** from your billable metrics
4. Turn `on` the toggle for **applying charges monthly**
By switching on, **all the charges** will be invoiced monthly even if the plan is yearly.
ℹ️ The last invoice is gathering both the subscription and the usage-based charges
## Events list
You are now able to view all the ingested events sent from your application to Lago. We called this feature `Events list` because it makes the event ingestion easier and more understandable.
1. Access the `Developer` sidebar item
2. Click the `Events` tab
3. Take a look at the latest events ingested
ℹ️ If an event you sent is not shown in the UI, it means that it has not been ingested by Lago
This events list is also helpul to warn you for 2 specific cases:
1. **Warning 1** - The event code is not related to an existing billable metric
2. **Warning 2** - The property sent does not match the aggregation property defined in your billable metric
## Add-ons
Add-ons are now available on Lago. Create add-ons to apply one-time fees (e.g. setup fee, one-time purchase, etc.) and generate the corresponding invoices instantly.
Full documentation [available here](/guide/one-off-invoices/create-add-ons).
## Pay-as-you-go template
We've added a new template to our collection: [click here](https://www.getlago.com/resources/templates/algolia) to learn how to replicate Algolia's pay-as-you-go pricing.
It's a great starting point for companies whose pricing fully depends on usage, such as cloud service providers and API companies.
With Lago, you can adapt this template to your products and services, using some of our most popular features, including the ['sum' aggregation type](/guide/billable-metrics/aggregation-types) and the [package charge model](/guide/plans/charges#charge-models).
## Coupons
Introducing coupons, a new feature that allows you to offer discounts to your customers.
Full documentation [available here](/guide/coupons).
## Subscription changes
You can now modify the subscription assigned to a customer through the user interface.
To learn how to upgrade or downgrade a subscription and how it affects billing, please refer to the documentation.
## Package pricing for charges
It is now possible to apply a [package pricing model](/guide/plans/charges#charge-models) to a charge. To do so:
1. Select an existing plan (or create a new one)
2. Add a charge
3. Select the package pricing model
This new pricing model allows you to apply a flat fee to a range of units. The price will be fixed for the entire range, regardless of the number of units consumed by the customer during the billing period.
## Percentage charge model
Inside the **plan**, when creating a charge, you can now select the **percentage charge model**.
This feature is useful for industries willing to take a `% + fixed fee` out of a usage-based features (for banking or charity industry, for instance). These fees are applied on the *units to be charged* (e.g. the aggregation result of your billable metric).
# About Lago
## 1. What is Lago?
[Lago](https://www.getlago.com/) is the leading open-source pricing solution focused on complex billing: multi-product/geographies, transactional, usage-based, subscription hybrids, etc, chosen by unicorns like Mistral (AI, \$640M raised at \$6 billion valuation), Accel-backed Swan (Embedded banking), Together.ai (AI, \$102.5M raised at \$1.25 billion valuation) or Groq (AI, \$300M raised at \$2.5 billion valuation).
Lago is API-first, the most loved billing solution on Github, and was voted Product of the day week, and month on Product Hunt.
Lago raised a total of [\$22M of funding](https://techcrunch.com/2024/03/14/lago-a-paris-based-open-source-billing-platform-banks-22m/) from investors including Y Combinator, FirstMark Capital, SignalFire, [Meghan Gill](https://www.linkedin.com/in/meghanpgill/), who has led the monetization efforts of MongoDB for 14 years, [Romain Huet](https://www.linkedin.com/in/romainhuet/), former head of Developer Relations at Stripe - now leading OpenAI developer experience, and [Clément Delangue](https://www.linkedin.com/in/clementdelangue/), CEO of AI open platform Hugging Face.
## 2. What does Lago do?
Lago helps businesses calculate how much their end-users need to pay, and make sure they’re paid.
This includes, but is not limited to:
* Managing subscriptions
* Metering consumption, or usage (e.g., for a telco provider: the number of minutes of a call ; for an electricity provider: the number of kwH used)
* Generating and sending invoices
* Triggering and tracking payments
* Managing customers’ accounts
**Features overview:**
Lago’s event-based architecture provides a solid foundation for building a
fair pricing model that scales with your business.
Lago supports all pricing models. Create pay-as-you-go and hybrid plans in
no time with our intuitive user interface or API.
Create engaging marketing campaigns and increase conversion with coupons
that customers can redeem to get a discount.
Create engaging marketing campaigns and increase conversion with coupons
that customers can redeem to get a discount.
Lago allows you to create one-time charges that are invoiced on the fly.
Depending on the configuration of your plans, Lago automatically calculates
what each customer owes you and generates invoices.
Unlock recurring revenue opportunities for pay-as-you-go pricing models with
Lago’s prepaid credit features.
Lago Billing takes integration to the next level, seamlessly integrating
with every aspect of your business operations.
Charge customers instantly while retaining the freedom to choose whether or
not to generate an invoice for the transaction.
Effortlessly integrate the customer portal into your application, providing
your customers with seamless access to detailed usage information and
invoice data.
Take control of your billing process by establishing minimum spending limits
for charges. With our platform, you can easily define the minimum amount
customers must meet for a usage-based component.
Providing a seamless integration of email communication with the billing
engine, allowing businesses to send professional invoices directly to their
customers' inbox.
Have the flexibility to make adjustments to customers' usage, even after the
billing cycle has ended. Fine-tune and modify usage details, ensuring that
you have complete control over your invoicing.
Simplify international billing. Bill your customers according to their
respective timezones.
Unlock customer satisfaction with credit notes issuance and customer
refunds. Streamline your operations and foster trust by handling credit
notes and refunds through our UI and API.
Check our documentation [here](https://docs.getlago.com/guide/introduction/welcome-to-lago), for more information.
Reproduce Notion, Slack, or Stripe’s pricing in a few clicks with our templates [here](https://www.getlago.com/resources/templates/all).
## 3. What is Lago origin story?
Lago was founded in 2021 by Anh-Tho and Raffi, who were among the earliest employees at Qonto.com – a \$5B B2B neobank. They led Qonto's revenue growth from pre-product to Series D, and built and scaled the monetization system that took the company from 0 to \$100M+ of revenue.
A fun fact was that when Raffi pitched the idea of Lago to Romain (a senior billing engineer at Qonto), he told him “no way”, and said he did want to quit his position at Qonto but he would “NEVER touch a billing system again”.
Step by step, Raffi managed to convince him he could channel this energy and experience to make sure fewer engineers would need to relive the billing nightmares he had to endure. And it worked!
At Qonto, they would always underestimate the engineering nightmare billing would create, and learned the hard way about the side effects: delayed launches at best, billing errors, resulting in churning users, and a growing “billing engineering” team that not only was expensive, but very hard to retain. The worst was that at some point, the “pricing strategy” nearly switched to “what’s the easiest option to implement”, rather than “what’s the best for the company”.
Raffi and Anh-Tho, and the founding Lago team then spent a lot of time carefully analyzing why no one had solved this huge problem yet, as they thought solid companies like Stripe or Chargebee had partially addressed it.
That’s how they built our conviction on the open-source and “platform” approach of Lago, to not be another “buy billing” option, but rather a “Lego '' that engineers build with to create their tailored monetization stack.
## 4. Does it work with my stack?
Yes. Lago is agnostic and can be used via:
* Our no-code interface, see it in action [here](https://youtu.be/dXnoMRetsr4)
* Our [API](https://doc.getlago.com/api-reference/intro)
* Our native integrations: Segment, Hightouch, Stripe Payments, Adyen, Salesforce, and many others, [here](https://www.getlago.com/integrations)
* One of our [backend libraries](https://doc.getlago.com/api-reference/intro) covering the main programming languages and tools
You can use Lago with your stack, whatever it is.
## 5. Is this supported properly?
Lago is a well funded project with thousands of stars on [Github](https://github.com/getlago/lago), in [very active development](https://github.com/getlago/lago-api/graphs/commit-activity), by our [core team](https://www.getlago.com/about-us) and our active community.
Additionally, we have strong uptime performance ([99,99%+ uptime](https://status.getlago.com/uptime/klj713fz3fcy)) and \<10 min median response time across support channels.
# About the software
## 1. How popular is the software?
Lago has thousands of users, thousands of stars on Github and great investors.
Lago is the most popular open-source repository solving for billing on Github, to give you a point of reference, the second most popular one was started ten years ago, Lago caught up fast!
It has been chosen by companies like:
* [Mistral.ai](http://Mistral.ai) – the open source genAI model provider, which raised more than \$600M with top VC ([see here](https://techcrunch.com/2024/06/11/paris-based-ai-startup-mistral-ai-raises-640-million/?guccounter=1)).
* [Together.ai](http://Together.ai) – the leading decentralized AI cloud provider, backed by Kleiner Perkins and Nvidia ([see here](https://techcrunch.com/2023/11/29/together-lands-102-5m-investment-to-grow-its-cloud-for-training-generative-ai/))
* [Groq](https://groq.com/) – the startup building AI-chip for fast inference, which raised more than \$640M from top VC ([see here](https://techcrunch.com/2024/08/05/ai-chip-startup-groq-lands-640m-to-challenge-nvidia/))
* [Juni](https://www.juni.co/) – the fintech company that develops a banking app for e-commerce.
* [Swan](https://swan.io) – the leading European Banking-as-a-Service (BaaS), backed by Accel and Creandum.
and many more.
To hear firsthand experiences from our users, explore Lago's [customer stories](https://www.getlago.com/customers/stories) and our [love wall](https://shoutout.io/lago).
## 2. Is the software updated regularly?
We release new versions every 2-3 weeks, our team is working relentlessly to improve the product.
Sign up to our newsletter, or follow us on [Linkedin](https://fr.linkedin.com/company/getlago) or [X](https://twitter.com/getlago?lang=en) (fka Twitter).
Our past product updates are [here](https://www.getlago.com/resources/updates).
## 3. How secure is Lago?
Keeping your data secure is critical to how Lago operates. Lago is SOC 2 Type 2 compliant. SOC 2 compliance ensures the secure storage and transmission of data. Type 2 compliance tests the design and effectiveness of the systems over a long period of time.
To protect access to and transmission of your data, Lago supports Single Sign-On (SSO) and Role-based access control (RBAC). SSO allows you to centrally manage your access and RBAC policies define how users interact with Lago, giving you the chance to minimize security vulnerability.
Learn more about security at Lago [here](https://getlago.com/docs/guide/security/rbac).
## 4. How is this different from the other billing tools?
A lot of companies continue building billing in-house, even if it means building systems that engineers hate to build, let alone maintain.
Lago has been conceived to address complex billing use cases, with a unique open-source approach, solving for:
* Transparency: you can inspect our code, have an overview on our pull requests, github issues, what our users say and how they use Lago.
* Control: you can opt for the convenience of Lago Cloud (our hosted solution) or choose the total control that our on-premise deployment offers: keep your data within your own system, and keep a direct access to all your usage, billing and payment data in your own infrastructure, with the highest level of granularity.
* Extensibility and connectivity: because engineers understand our code and infrastructure better.
Lago is the only open source metering and usage-based billing solution. A lot of closed source (aka ‘SaaS’) solutions exist (e.g., Stripe Billing, Zuora) but they require you to send your data to third-parties, to blindly trust a Chargebee‘black box’ with your most critical internal system (billing / revenue) and they take a cut on your revenue. We have put together these [product comparisons](https://www.getlago.com/resources/compare/compare-home) if you want to go further.
There are multiple open source billing offerings. However, Lago is the only open source software that gives you:
1. Real-time event-based usage metering
2. Subscription billing
3. Hybrid plans, mixing subscription and consumption (e.g., a usage-based billing plan that requires a recurring minimum spend per month)
4. A full fledge API to automate ‘self-serve/product-led’ plans, and an intuitive no-code user interface to configure ‘custom/enterprise’ plans
5. Additional features including: instant charges, modular couponing, spending minimums, grace periods, etc
## 5. I have a home-made billing infrastructure. How is Lago useful?
Billing is indeed much harder and costly for engineers than it might initially seem.
When getting started, it seems pretty straightforward – you decide on a price, and customers pay you. But as your business grows, things get trickier. It's like managing a puzzle where the pieces keep changing. You have to deal with dates, handle plan upgrades, track usage, avoid charging twice, remind customers to pay, and navigate the tax maze (we have written some posts on this topic [here](https://www.getlago.com/blog/why-billing-systems-are-a-nightmare-for-engineers) and [here](https://www.getlago.com/blog/the-4-biggest-problems-with-homemade-billing-systems)).
Lago is an open source metering and billing API tailored for usage-based pricing. Our API and architecture are open, so you can embed, fork and customize them as much as your pricing and internal processes require.
If you are interested, you can [get started here](https://www.getlago.com/get-started) or [book a demo](https://forms.gle/eT7zgqcvq8dgt94g7).
## 6. Can Lago handle high volume processing?
Lago is designed for usage-based billing and high-volume data processing. Its engine is able to handle hundreds of thousands events per second, whether they come in the form of logs or back-end events. Our infrastructure is made to scale to billions of events per month if needed. For more details, we have written about our infrastructure [here](https://github.com/getlago/lago/wiki/Using-Clickhouse-to-scale-an-events-engine).
## 7. I’m an AI company. How is Lago helpful?
Engineering teams in AI companies should be 100% focused on monetizing, not getting bogged down by [billing nightmares](https://news.ycombinator.com/item?id=31424450).
That's where Lago, with its open-source metering and billing engine, comes in. Lago has already been chosen by leading AI companies such as [Mistral](https://mistral.ai/fr/), [Together.ai](http://Together.ai), [Groq.com](http://Groq.com), or [Cerebrium](https://www.cerebrium.ai/), for instance.
Lago’s infrastructure handles hundreds of thousands events per second and makes it easy to offer market-practices pricing features like per-token pricing, prepaid credits, real-time consumption monitoring and progressive billing.
Use one of our templates to replicate the pricing of [OpenAI](https://getlago.com/docs/templates/per-token/openai) or [Mistral](https://getlago.com/docs/templates/per-token/mistral).
# Community
## 1. What’s the community like?
Lago Community thrives through the active engagement of 6.6K+ users and developers, making it the largest and fastest-growing billing community on GitHub (see [here](https://github.com/getlago/lago)). It serves as the central hub where users and developers can seek support, request features and contribute to the ongoing enhancement of Lago's product.
You can also join hundreds of billing and pricing professionals in our [Slack Community](https://www.getlago.com/slack).
## 2. How can I contribute?
There are many ways to contribute to the Lago community. You can:
* Share your expertise by answering questions on the Lago Community ([Join our Slack](https://www.getlago.com/slack))
* Write blog posts or tutorials about Lago
* Participate in Lago surveys and user interviews
* Contribute to the Lago codebase (learn more [here](https://github.com/getlago/lago/blob/main/CONTRIBUTING.md))
* Report bugs or suggesting improvements ([here](https://github.com/getlago/lago/blob/main/CONTRIBUTING.md))
For instance, our community played a pivotal role in introducing the "[Latest](https://docs.getlago.com/guide/billable-metrics/aggregation-types/overview)" aggregation type to Lago's product. Additionally, we regularly receive translation contributions from users in languages such as Italian, Spanish, and Norwegian.
Thanks to valuable contributions from our users, our community continues to grow stronger!
## 3. Can I suggest new features?
Yes. Lago warmly welcomes feature suggestions. Your ideas are valuable to us. You can suggest new features [here](https://getlago.canny.io/feature-requests). We will carefully review and prioritize highly requested ones, providing regular updates on their progress.
# Deployment
## 1. Is this hard to set up?
Lago is easy to set up, you can run our app in a few clicks by downloading our [Docker image](https://doc.getlago.com/guide/self-hosted/docker).
If you have any questions, or want access to our [premium features and/or our cloud version (paying)](https://www.getlago.com/pricing), reach out via [Slack](https://www.getlago.com/slack) or send an email to [hello@getlago.com](mailto:hello@getlago.com); we'll get back to you shortly.
## 2. Can I self-host?
Yes. Lago’s self-hosted version can be deployed on any infrastructure. We provide detailed instructions on [how to self-host Lago](https://docs.getlago.com/guide/self-hosted/docker).
## 3. How do I deploy?
There are three options:
1. Lago Self-hosted:
* Self-hosting the open-source product - Free, and self-serve [here](https://doc.getlago.com/guide/self-hosted/docker)
* Self-hosting the premium product - Reach out [here](https://docs.google.com/forms/d/e/1FAIpQLSfKwXdwe3jIpPJuPs2Nmkw_3GqoUOEP1YxQ3B6frYfGgYJ11g/viewform?usp=send_form)
2. Lago Cloud, with either US or EU hosting - There are only a few spots available to use this product at the moment, so we’ll ask you a couple of questions first, reach out [here](https://docs.google.com/forms/d/e/1FAIpQLSfKwXdwe3jIpPJuPs2Nmkw_3GqoUOEP1YxQ3B6frYfGgYJ11g/viewform?usp=send_form)
3. Hybrid hosting: for Enterprise customers, Lago also offers cloud-prem or Virtual Private Cloud (VPC) deployments options
## 4. Can I get it live with my favorite hosting option?
See our instructions to deploy Lago’s open source product [here](https://doc.getlago.com/guide/self-hosted/docker).
Want to set it up differently? (Raise an issue)([https://github.com/getlago/lago/issues](https://github.com/getlago/lago/issues)) in the repo.
# General
## 1. Is billing that hard for engineers?
Yes. Billing is indeed much harder for engineers than it might initially seem. Imagine you're starting a business, and you want to charge your customers for your products or services. At first, it seems pretty straightforward – you decide on a price, and customers pay you. But as your business grows, things get trickier. It's like managing a puzzle where the pieces keep changing. You have to deal with dates, handle plan upgrades, track usage, avoid charging twice, remind customers to pay, and navigate the tax maze (see more [here](https://www.getlago.com/blog/why-billing-systems-are-a-nightmare-for-engineers)).
For example, deciding how often to charge your customers for subscriptions and charges might sound simple, like choosing between weekly, monthly, or yearly billing. But it's more complex than it appears. You also need to factor in things like leap years, offering free trial periods, and deciding how to handle pro-rata pricing. And if you ever decide to switch from billing based on 'anniversary' dates to calendar dates, that adds even more complexity to the mix.
At Lago, we've adopted a radical approach – we're building an open source billing API for product-led SaaS. Our API and architecture are open, so that you can embed, fork and customize them as much as your pricing and internal processes require.
If you're interested, you can [get started here](https://www.getlago.com/get-started) or [book a demo](https://forms.gle/eT7zgqcvq8dgt94g7).
## 2. How is Lago different from Stripe? Can Lago replace it?
Lago is an open source metering and billing solution, whereas Stripe primarily focuses on payment processing.
Stripe offers 21 products with separate fees (see more [here](https://www.getlago.com/blog/we-crunched-the-fees-of-stripes-21-products)), including Stripe Billing and Stripe Invoicing.
Lago can replace Stripe for some services such as billing, invoicing and potentially [more](https://www.getlago.com/blog/calculating-stripe-mrr-is-difficult), but it does not process payments directly. Businesses using Lago will need a separate payment processor. Lago calculates how much you should charge a user and when, and sends this information to your chosen payment gateway(s) (Lago is agnostic) for the actual payment processing.
See detailed comparison of Stripe Billing vs. Lago [here](https://www.getlago.com/resources/compare/lago-vs-stripe).
## 3. Is Lago cheaper than Stripe?
Stripe Billing will cost you 0.5% (and up to 0.8%) of your transaction volume, on top of Stripe Payments (starts at 2.9% + \$0.30 per successful card charge). With the full vendor lock-in of Stripe, you might stack dozens of fees that are directly impacting your own revenue. Once again, Stripe has 21 products and each of them has their own pricing (see more [here](https://www.getlago.com/blog/we-crunched-the-fees-of-stripes-21-products)).
Lago offers a forever-free open source solution for small businesses, allowing access to fundamental billing features. Besides, Lago provides Enterprise plans with access to premium features listed [here](https://www.getlago.com/pricing).
See detailed comparison of Stripe Billing vs. Lago [here](https://www.getlago.com/resources/compare/lago-vs-stripe).
## 4. How is Lago different from Chargebee?
Chargebee is not designed for usage-based billing. Lago is.
Lago is designed for usage-based pricing models, providing a high level of flexibility and support complex usage-based scenarios. Chargebee supports standard usage-based models (e.g. \$20 per user) but may not be flexible enough for businesses that need support for complex usage-based pricing models (e.g., PayPal's per-transaction pricing). Chargebee limits the maximum number of usages that can be recorded for a subscription is 5,000, over its lifetime.
Lago has no rate limit for usage-based billing events, allowing for high volume processing. Chargebee has a rate limit of 100 simultaneous requests per minute, which could prevent you from sending granular usage when you start scaling your number of customers.
Additionally, Lago, being an open source solution, offers complete transparency, allowing engineers to audit its code and even build on top of it, which Chargebee does not allow.
See detailed comparison of Chargebee vs. Lago [here](https://www.getlago.com/resources/compare/lago-vs-chargebee).
## 5. Is Lago cheaper than Chargebee?
Chargebee offers two services including billing and retention with separate fees. For billing:
* Starter plan: No flat fee, with the first \$250K of cumulative billing included; 0.75% on billing thereafter. This plan includes basic billing features.
* Performance plan: \$599 monthly flat fee for up to \$100K of monthly billing; 0.75% on billing thereafter. This plan offers access to some advanced features.
* Enterprise plan: Custom pricing.
Lago offers a forever-free open source solution for small businesses, allowing access to fundamental billing features. Besides, Lago provides Enterprise Plans with access to premium features, as listed [here](https://www.getlago.com/pricing).
See detailed comparison of Chargebee vs. Lago [here](https://www.getlago.com/resources/compare/lago-vs-chargebee).
## 6. Can Lago be used by non-tech users?
Yes. Lago is a developer-first product with an intuitive interface. All actions in Lago can be performed via the API or the user interface, making Lago accessible to both tech-savvy and non-technical users alike.
For **Engineers**: Lago is Developer-first and API-first, offering high flexibility and ability to build on top of it. Lago can handle a high volume of events and works seamlessly with your existing tools.
For **Product managers**: Lago can adapt to any pricing model, and our easy-to-use interface lets non-technical teams manage billing without developer assistance. You can retrieve billing data for integration to your BI tools. You can also use it to trigger automations and implement alerting as needed.
For **Finance leaders**: Lago streamlines invoicing by automating charge calculations, supports various pricing plans, and helps track payments. Lago ensures the invoicing and cash collection process under your control. For instance, check who paid their invoices in a glance to improve cash collection. It also integrates billing data into your tools for better revenue insights.
# Pricing
## 1. Is Lago free?
Lago offers a forever-free open source solution offering access to fundamental billing features. Besides, Lago also offers paying plans with access to premium features listed [here](https://www.getlago.com/pricing).
## 2. How is your pricing structured?
Our pricing is structured in packages that are tailored to specific company stages: early, scaling, or more on the enterprise side.
We don’t take a cut on revenue, as we don’t think it’s a pricing strategy that can be worthwhile in the long term.
We’re willing to grow with our customers sustainably (if they are successful, we are successful too) so we have included a usage-based dimension (e.g., number of events ingested, invoices generated, or active customers) in our packages
Contact us at [hello@getlago.com](mailto:hello@getlago.com) to discuss what features and usage volumes work best for your company.
## 3. Can I self-host the Premium features?
Yes. Lago offers Enterprise plans with access to premium features listed [here](https://www.getlago.com/pricing). You have the flexibility to choose between cloud hosting or self-hosting options.
Please reach out via [Slack](https://lago-community.slack.com/ssb/redirect) or [hello@getlago.com](mailto:hello@getlago.com) for further details.
## 4. Can I have a free trial for Lago Premium?
You can use and/or try Lago forever-free product by downloading our self-hosted and open source product [here](https://doc.getlago.com/guide/introduction/welcome-to-lago). We unfortunately do not offer free trials for our premium plans (cloud or self-hosted).
In specific cases, our Solution Engineering team can organize ‘proofs of concepts’. Reach out via [Slack](https://www.getlago.com/slack) or [hello@getlago.com](mailto:hello@getlago.com) if you need help testing Lago.
# Product features
## 1. Does Lago support prepaid credits?
Yes. Prepaid credits are a great way to give customers better spend visibility and facilitate payment collection in advance.
To prepay for usage with lago follow this simple steps:
1. Create a new wallet for prepaid credits;
2. Assign a value for each credit (eg. 1 credit equals 1\$);
3. Specify the number of credits to purchase; and
4. Configure recurring top-up rules based on real-time consumption (threshold or interval top-ups)
See a real-life example of prepaid credits with Mistral [here](https://docs.getlago.com/templates/per-token/mistral#step-3-prepay-usage-with-credits).
## 2. Which payment methods does Lago support?
Lago is agnostic and enables you to connect with any payment providers. Lago is already natively integrated with several payment providers ([see here](https://docs.getlago.com/guide/payments/overview)).
## 3. Does Lago support invoicing?
Yes. Without charging a percentage of billings, every plan includes built-in invoicing automation with native invoice generation.
Lago enables you to issue invoices and send them to your customers via email. Lago offers advanced invoicing features, allowing you to customize invoice templates, and to include [customer metadata](https://docs.getlago.com/guide/customers/customer-metadata) & [credit notes](https://github.com/getlago/lago/wiki/Refunds,-Coupons-&-Credit-Notes:-why-they-are-different) in invoices and set [invoice grace periods](https://www.getlago.com/blog/grace-period-to-adjust-invoice-usage). These features can enhance invoicing operations and compliance.
Additionally, Lago offers support for multiple languages for invoices and emails, making it a versatile solution for businesses operating in various countries or aiming for global expansion ([see more here](https://docs.getlago.com/api-reference/resources/locales)).
Companies also have the option to integrate our billing engine with an existing invoicing provider like Quickbooks, Netsuite, Bill.com, or Stripe. Learn more [here](https://docs.getlago.com/integrations/introduction).
## 4. Does Lago provide a customer self-service portal?
Yes. Lago allows you to effortlessly integrate the customer portal into your application, providing your customers with seamless access to detailed usage information and invoice data.
## 5. Does Lago provide Analytics and Reporting?
Lago is your go-to solution for in-depth analytics of your billing data. This gives you access to accurate revenue computation with ease and other critical financial information.
Analytics dashboard are accessible through both user interface and dedicated API endpoints to obtain the insights that matter most to you, like your monthly recurring revenues (if you use Stripe, you probably know how [difficult it is to gather this info](https://www.getlago.com/blog/calculating-stripe-mrr-is-difficult))
Learn more about analytics [here](https://docs.getlago.com/guide/analytics/overview).
## 6. Does Lago support different time zones?
Yes. Lago allows you to set time zones at a customer level, ensuring that usage ingestion, expiry dates and billing will be triggered based on the time zone of your customer.
Read more about why time zones matter [here](https://www.getlago.com/blog/bill-your-customers-in-their-timezone-not-yours).
## 7. What integrations does Lago support?
All Lago’s plans offer native integrations with third party tools for payments (Stripe Payments, GoCardless, Adyen), accounting (NetSuite, QuickBooks), taxes (Anrok), CRM (Salesforce) and others.
You can learn more about integrations [here](https://getlago.com/docs/integrations/introduction).
## 8. Does Lago support taxation?
Lago features automatic European tax detection integration for your customers. Learn more about Lago EU Taxes integration [here](https://getlago.com/docs/integrations/taxes/lago-eu-taxes).
You can also integrate with Anrok, the global sales tax platform for software companies. Learn more about this integration [here](https://getlago.com/docs/integrations/introduction#taxes-integrations).
## 9. Does Lago process payments?
Lago does not process payments directly but enables you to integrate with any payment processors (Stripe Payments, GoCardless, Adyen, etc). Learn more about payment integrations [here](https://getlago.com/docs/integrations/introduction#payments-integrations).
Lago will process and calculate how much you should charge a user and when, and send this information to your chosen payment gateway, so that your user can proceed to the actual payment. We also allow you to monitor payment status and track refunds.
# Gross revenue
Gross revenue represents the total income generated by your organization in a single month, giving you a complete overview of your financial performance.
We ensure a comprehensive approach, encompassing all types of discounts, such as credit notes, coupons, and credits, to provide you with a precise picture of your gross revenue.
In essence, it's the amount you should expect to receive every month.
**Our gross revenue calculation considers the following factors:**
1. All `finalized` invoices, whether related to subscriptions or usage;
2. Pay in advance fees, whether they are invoiceable or not;
3. Invoices related to prepaid credits from wallets;
4. One-off invoices; and
5. Deducting the credit note amounts `refunded` to customers.
To access the Gross Revenue analytics dashboard:
1. Navigate to the "Analytics" section; and
2. Access the "Gross Revenue" Dashboard.
```bash Get Gross Revenue
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/gross_revenue?external_customer_id=hooli_1234¤cy=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
The generated amounts are in cents, making it compatible with different currencies.
```sql SQL Query used by Lago
--- Start date of the query is the organization creation date
WITH organization_creation_date AS (
SELECT
DATE_TRUNC('month', o.created_at) AS start_month
FROM organizations o
WHERE o.id = '__YOUR_ORGANIZATION_ID__'
),
--- Generate a number of date series in the future
all_months AS (
SELECT
generate_series(
(SELECT start_month FROM organization_creation_date),
DATE_TRUNC('month', CURRENT_DATE + INTERVAL '10 years'),
interval '1 month'
) AS month
),
--- Get value for all issued invoices
issued_invoices AS (
SELECT
i.id,
i.issuing_date,
i.total_amount_cents::float AS amount_cents,
i.currency,
COALESCE(SUM(refund_amount_cents::float),0) AS total_refund_amount_cents
FROM invoices i
LEFT JOIN customers c ON i.customer_id = c.id
LEFT JOIN credit_notes cn ON cn.invoice_id = i.id
WHERE i.organization_id = '__YOUR_ORGANIZATION_ID__'
AND i.status = 1
---AND c.external_id = 'hooli_1234' --- FILTER BY CUSTOMER
GROUP BY i.id, i.issuing_date, i.total_amount_cents, i.currency
ORDER BY i.issuing_date ASC
),
--- Get value for all instant charges (paid in advance but not invoiceable)
instant_charges AS (
SELECT
f.id,
f.created_at AS issuing_date,
f.amount_cents AS amount_cents,
f.amount_currency AS currency,
0 AS total_refund_amount_cents
FROM fees f
LEFT JOIN subscriptions s ON f.subscription_id = s.id
LEFT JOIN customers c ON c.id = s.customer_id
WHERE c.organization_id = '__YOUR_ORGANIZATION_ID__'
AND f.invoice_id IS NULL
AND f.pay_in_advance IS TRUE
---AND c.external_id = 'hooli_1234' --- FILTER BY CUSTOMER
),
--- Combine data to get total of gross revenue
combined_data AS (
SELECT
DATE_TRUNC('month', issuing_date) AS month,
currency,
COALESCE(SUM(amount_cents), 0) AS amount_cents,
COALESCE(SUM(total_refund_amount_cents), 0) AS total_refund_amount_cents
FROM (
SELECT * FROM issued_invoices
UNION ALL
SELECT * FROM instant_charges
) AS gross_revenue
GROUP BY month, currency, total_refund_amount_cents
)
--- Get gross revenue month over month
SELECT
am.month,
cd.currency,
SUM(cd.amount_cents - cd.total_refund_amount_cents) AS amount_cents
FROM all_months am
LEFT JOIN combined_data cd ON am.month = cd.month
WHERE am.month <= DATE_TRUNC('month', CURRENT_DATE)
---AND am.month >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '11 months') --- LAST 12 MONTHS
AND cd.amount_cents IS NOT NULL
--- AND cd.currency = 'EUR'
GROUP BY am.month, cd.currency
ORDER BY am.month
```
# Invoice collection
**PREMIUM FEATURE** ✨
This dashboard is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
Our dashboard empowers you with insights into the number of invoices and their respective values across all payment statuses.
This means you can easily track the count of invoices with failed, pending, or successful payment statuses and ease your collection.
By simply clicking on any of the rows, you can gain access to a detailed list of invoices categorized by their status.
This feature proves valuable when you need to initiate a new payment intent or take specific actions related to invoice management.
To access the Invoice collection analytics dashboard:
1. Navigate to the "Analytics" section; and
2. Access the "Outstanding invoices" Dashboard.
```bash Get Oustanding Invoices
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/invoice_collection?currency=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
The generated amounts are in cents, making it compatible with different currencies.
```sql SQL Query used by Lago
--- Get start date of the organization
WITH organization_creation_date AS (
SELECT
DATE_TRUNC('month', o.created_at) AS start_month
FROM organizations o
WHERE o.id = '__YOUR_ORGANIZATION_ID__'
)
--- Generate a series of months
, all_months AS (
SELECT
generate_series(
(SELECT start_month FROM organization_creation_date),
DATE_TRUNC('month', CURRENT_DATE + INTERVAL '10 years'),
interval '1 month'
) AS month
)
--- Get invoice number and value per status
,invoices_per_status AS (
SELECT
DATE_TRUNC('month', i.issuing_date) AS month,
i.currency,
CASE
WHEN i.payment_status = 0 THEN 'pending'
WHEN i.payment_status = 1 THEN 'paid'
WHEN i.payment_status = 2 THEN 'failed'
END AS payment_status,
COALESCE(COUNT(*), 0) AS number_invoices,
COALESCE(SUM(i.total_amount_cents::float), 0) AS amount_cents
FROM invoices i
WHERE i.organization_id = '__YOUR_ORGANIZATION_ID__'
AND i.status = 1 --- ONLY FINALIZED INVOICES
GROUP BY payment_status, month, currency
)
--- Get invoice total and amount per status per month till the current month
SELECT
am.month,
payment_status,
currency,
COALESCE(number_invoices, 0) AS number_invoices,
COALESCE(amount_cents, 0) AS amount_cents
FROM all_months am
LEFT JOIN invoices_per_status ips ON ips.month = am.month AND ips.payment_status IS NOT NULL
WHERE am.month <= DATE_TRUNC('month', CURRENT_DATE)
AND payment_status IS NOT NULL
---AND currency = '' --- Filter by currency if needed
ORDER BY am.month, payment_status, currency;
```
# Overdue invoices
The Overdue Invoices dashboard displays the total amount from your finalized invoices that are either pending or failed and have passed their due date. It does not include voided or disputed invoices. At a glance, you can see what your customers owe you, providing quick insight into the state of your revenue collection.
To access the Overdue invoices dashboard:
1. Navigate to the "Analytics" section; and
2. Access the "Overdue invoices" Dashboard.
Our overdue balance calculation considers the following factors:
* Finalized invoices;
* With pending or failed as a payment status; and
* A due date that is past;
It is not taking into account invoices that are disputed or voided.
```bash Get Overdue balance
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/overdue_balance?currency=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
The generated amounts are in cents, making it compatible with different currencies.
```sql SQL Query used by Lago
--- Start date of the query is the organization creation date
WITH organization_creation_date AS (
SELECT
DATE_TRUNC('month', o.created_at) AS start_month
FROM organizations o
WHERE o.id = '__YOUR_ORGANIZATION_ID__'
),
--- Generate a number of date series in the future
all_months AS (
SELECT
generate_series(
(SELECT start_month FROM organization_creation_date),
DATE_TRUNC('month', CURRENT_DATE + INTERVAL '10 years'),
interval '1 month'
) AS month
),
--- Get total of overdue invoices
payment_overdue_invoices AS (
SELECT
DATE_TRUNC('month', payment_due_date) AS month,
i.currency,
COALESCE(SUM(total_amount_cents), 0) AS total_amount_cents,
array_agg(DISTINCT i.id) AS ids
FROM invoices i
LEFT JOIN customers c ON i.customer_id = c.id
WHERE i.organization_id = :organization_id
AND i.payment_overdue IS TRUE
---AND c.external_id = 'hooli_1234' --- FILTER BY CUSTOMER
GROUP BY month, i.currency, total_amount_cents
ORDER BY month ASC
)
--- Get overdue balances month over month
SELECT
am.month,
#{select_currency_sql},
SUM(invs.total_amount_cents) AS amount_cents,
jsonb_agg(DISTINCT invs.ids) AS lago_invoice_ids
FROM all_months am
LEFT JOIN payment_overdue_invoices invs ON am.month = invs.month
WHERE am.month <= DATE_TRUNC('month', CURRENT_DATE)
---AND am.month >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '11 months') --- LAST 12 MONTHS
--- AND cd.currency = 'EUR'
AND invs.total_amount_cents IS NOT NULL
GROUP BY am.month, invs.currency
ORDER BY am.month;
```
# Monthly Recurring Revenue (MRR)
**PREMIUM FEATURE** ✨
This dashboard is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
Monthly Recurring Revenue (MRR) serves as a crucial indicator of your subscription-based revenue stream.
It encapsulates the total monthly revenue derived from subscriptions that is recurring. It's important to highlight that our MRR calculation
method takes into account all types of coupons and taxes. We take a holistic approach to provide you with an accurate representation
of your recurring revenue.
It's worth noting that Lago's MRR calculations solely pertain to `subscription` fees. Usage-based metrics,
whether recurring or metered, are not factored into the MRR calculations. This distinction ensures that your MRR figures
specifically reflect your subscription-based revenue, helping you gain a clear understanding of your core financial
performance.
**Here's our MRR calculation method:**
* Revenue from `monthly` subscription invoices is included in the MRR for the month in which the invoice is issued.
* Revenue from `quarterly` subscription invoices is distributed evenly over three months. This distribution applies to fees paid in advance (allocated to the next remaining months depending on calendar or anniversary billing) as well as to fees paid in arrears (allocated to the preceding months depending on calendar or anniversary billing).
* Revenue from `yearly` subscription invoices is distributed evenly over twelve months. This allocation is applicable for fees paid in advance (spread over the next remaining months depending on calendar or anniversary billing) and for fees paid in arrears (spread over the previous months depending on calendar or anniversary billing).
* Revenue from `weekly` subscription invoices, the total revenue from all invoices issued within a month is summed up. This total is then divided by the number of invoices issued during that month, and the result is multiplied by 4.33, representing the average number of weeks in a month.
Please note that the UI's MRR total summary displays the MRR from the most recently **completed** billing month.
To access the MRR analytics dashboard:
1. Navigate to the "Analytics" section; and
2. Access the "Monthly Recurring Revenue" Dashboard.
```bash Get MRR
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/mrr?currency=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
The generated amounts are in cents, making it compatible with different currencies.
```sql SQL Query used by Lago
--- Organization creation date is the start of this report
WITH organization_creation_date AS (
SELECT
DATE_TRUNC('month', o.created_at) AS month
FROM organizations o
WHERE o.id = '__YOUR_ORGANIZATION_ID__'
),
--- Generate series of month
all_months AS (
SELECT
*
FROM generate_series(
(SELECT min(month) FROM organization_creation_date),
date_trunc('month', now()) + interval '10 years',
interval '1 month'
) AS month
),
--- Get invoice details for recurring subscriptions with finalized invoices and number of months billed
invoice_details AS (
SELECT
f.subscription_id,
f.invoice_id,
c.name,
((f.amount_cents - f.precise_coupons_amount_cents) + f.taxes_amount_cents) AS amount_cents,
f.amount_currency AS currency,
i.issuing_date,
(EXTRACT(DAY FROM CAST(properties ->> 'to_datetime' AS timestamp) - CAST(properties ->> 'from_datetime' AS timestamp))
+ EXTRACT(HOUR FROM CAST(properties ->> 'to_datetime' AS timestamp) - CAST(properties ->> 'from_datetime' AS timestamp)) / 24
+ EXTRACT(MINUTE FROM CAST(properties ->> 'to_datetime' AS timestamp) - CAST(properties ->> 'from_datetime' AS timestamp)) / 1440) / 30.44 AS billed_months,
p.pay_in_advance,
CASE
WHEN p.interval = 0 THEN 'weekly'
WHEN p.interval = 1 THEN 'monthly'
WHEN p.interval = 2 THEN 'yearly'
WHEN p.interval = 3 THEN 'quarterly'
END AS plan_interval
FROM fees f
LEFT JOIN invoices i ON f.invoice_id = i.id
LEFT JOIN customers c ON c.id = i.customer_id
LEFT JOIN organizations o ON o.id = c.organization_id
LEFT JOIN subscriptions s ON f.subscription_id = s.id
LEFT JOIN plans p ON p.id = s.plan_id
WHERE fee_type = 2
AND c.organization_id = '__YOUR_ORGANIZATION_ID__'
AND i.status = 1
ORDER BY issuing_date ASC
)
--- Distribute quarterly revenue prorated for the next months
,quarterly_advance AS (
SELECT
DATE_TRUNC('month', issuing_date) + INTERVAL '1 month' * gs.month_index AS month,
CASE
WHEN gs.month_index = 0 THEN (amount_cents / billed_months) * (DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - issuing_date) / DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - DATE_TRUNC('month', issuing_date)))
WHEN gs.month_index = CEIL(billed_months) - 1 THEN (amount_cents - (amount_cents / billed_months) * (FLOOR(billed_months) - 1 + (DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - issuing_date) / DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - DATE_TRUNC('month', issuing_date)))))
ELSE amount_cents / billed_months
END AS amount_cents,
currency,
name
FROM invoice_details,
LATERAL GENERATE_SERIES(0, CEIL(billed_months) - 1) AS gs(month_index)
WHERE pay_in_advance = TRUE
AND plan_interval = 'quarterly'
)
--- Distribute quarterly revenue prorated for the past months
,quarterly_arrears AS (
SELECT
DATE_TRUNC('month', issuing_date) - INTERVAL '1 month' * gs.month_index AS month,
CASE
WHEN gs.month_index < CEIL(billed_months::numeric) - 1 THEN
amount_cents::numeric / billed_months::numeric
ELSE
amount_cents::numeric - (amount_cents::numeric / billed_months::numeric) * (CEIL(billed_months::numeric) - 1)
END AS amount_cents,
currency,
name
FROM invoice_details,
LATERAL GENERATE_SERIES(0, CEIL(billed_months::numeric) - 1) AS gs(month_index)
WHERE pay_in_advance = FALSE
AND plan_interval = 'quarterly'
)
--- Distribute yearly revenue prorated for the next months
,yearly_advance AS (
SELECT
DATE_TRUNC('month', issuing_date) + INTERVAL '1 month' * gs.month_index AS month,
CASE
WHEN gs.month_index = 0 THEN (amount_cents / billed_months) * (DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - issuing_date) / DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - DATE_TRUNC('month', issuing_date)))
WHEN gs.month_index = CEIL(billed_months) - 1 THEN (amount_cents - (amount_cents / billed_months) * (FLOOR(billed_months) - 1 + (DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - issuing_date) / DATE_PART('day', DATE_TRUNC('month', issuing_date + INTERVAL '1 month') - DATE_TRUNC('month', issuing_date)))))
ELSE amount_cents / billed_months
END AS amount_cents,
currency,
name
FROM invoice_details,
LATERAL GENERATE_SERIES(0, CEIL(billed_months) - 1) AS gs(month_index)
WHERE pay_in_advance = TRUE
AND plan_interval = 'yearly'
)
--- Distribute yearly revenue prorated for the past months
,yearly_arrears AS (
SELECT
DATE_TRUNC('month', issuing_date) - INTERVAL '1 month' * gs.month_index AS month,
CASE
WHEN gs.month_index < CEIL(billed_months::numeric) - 1 THEN
amount_cents::numeric / billed_months::numeric
ELSE
amount_cents::numeric - (amount_cents::numeric / billed_months::numeric) * (CEIL(billed_months::numeric) - 1)
END AS amount_cents,
currency,
name
FROM invoice_details,
LATERAL GENERATE_SERIES(0, CEIL(billed_months::numeric) - 1) AS gs(month_index)
WHERE pay_in_advance = FALSE
AND plan_interval = 'yearly'
)
--- Distribute monthly revenue for the current month of issuing
,monthly AS (
SELECT
DATE_TRUNC('month', issuing_date) - interval '1 month' * generate_series(0, 0, -1) AS month,
amount_cents,
currency
FROM invoice_details
WHERE plan_interval = 'monthly'
)
--- Distribute weekly revenue by dividing number of invoices in a month by 4.33 (average number of weeks in a month)
,weekly AS (
SELECT
DATE_TRUNC('month', issuing_date) - interval '1 month' * generate_series(0, 0, -1) AS month,
currency,
(SUM(amount_cents) / COUNT(*)) * 4.33 AS amount_cents
FROM invoice_details
WHERE plan_interval = 'weekly'
GROUP BY month, currency
)
,consolidated_mrr AS (
SELECT month, amount_cents::numeric, currency
FROM quarterly_arrears
UNION ALL
SELECT month, amount_cents::numeric, currency
FROM quarterly_advance
UNION ALL
SELECT month, amount_cents::numeric, currency
FROM yearly_arrears
UNION ALL
SELECT month, amount_cents::numeric, currency
FROM yearly_advance
UNION ALL
SELECT month, amount_cents::numeric, currency
FROM monthly
UNION ALL
SELECT month, amount_cents::numeric, currency
FROM weekly
)
SELECT
am.month,
cm.currency,
COALESCE(SUM(cm.amount_cents),0) AS amount_cents
FROM all_months am
LEFT JOIN consolidated_mrr cm ON cm.month = am.month
WHERE am.month <= DATE_TRUNC('month', CURRENT_DATE)
AND am.month >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '11 months') --- LAST 12 MONTHS
---AND cm.currency = ''
GROUP BY am.month, cm.currency
ORDER BY am.month ASC
```
# Overview
Lago is your go-to solution for in-depth billing analytics data, enabling you to accurately calculate revenue with ease.
Our commitment to delivering valuable insights drives us to regularly expand our suite of revenue dashboards.
These dashboards are not just a feature; they're the very first thing you encounter when you log in to your Lago account,
ensuring you have immediate access to critical financial information. Additionally, users can access this data via our API for seamless integration.
## Currency filter
Keep in mind that our revenue analytics dashboards are segmented by currency.
If you have invoices in multiple currencies, please note that no conversion rate is applied.
## Time filter
Within the user interface, you have the ability to filter metrics based on timeframes. Your options include:
* `Yearly`: Covers the last 12 months
* `Monthly`: Focuses on the current month
* `Quarterly`: Encompasses the past 4 months
## API-Driven revenue insights
At Lago, our analytics dashboards are accessible through both the user interface and dedicated API endpoints.
When interacting with our APIs, you have the flexibility to fine-tune your data retrieval by incorporating currency-based
filters. This means you can seamlessly obtain the insights that matter most to you, all while harnessing the power of
Lago's analytics capabilities.
## Data caching strategy
Lago optimizes data retrieval for revenue analytics in both UI and API endpoints through strategic caching.
This ensures faster performance. However, it's important to note that **this data is refreshed every 4 hours**.
Consequently, there may be a slight delay in reflecting the most current revenue data at the time of access.
## Data models
If you're looking to craft custom queries from our self-hosted database, here are key insights to empower your interaction with our data models:
**Invoice Types**:
* `subscription`: 0
* `add_on`: 1
* `credit`: 2
* `one_off`: 3
**Payment Status**:
* `pending`: 0
* `succeeded`: 1
* `failed`: 2
**Invoice Status**
* `draft`: 0
* `finalized`: 1
* `voided`: 2
# Aggregation examples
Imagine you are a Tracking API company (such as
[Segment.com](https://www.segment.com/)). For the same events received, the
result provided by the aggregation types proposed by Lago is completely
different. This result is used to charge your customers.
## Example of events received[](#example-of-events-received "Direct link to heading")
You decided to charge the `Tracked Pages`. **This is your Billable metric.**
Here are the 2 events sent by your backend to Lago, based on the consumption of
a customer:
```json Event received n°1
{
"transaction_id": "1111-1111-1111-1111",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "tracked_pages",
"properties": {
"tracked_user_id": "1234-5678-9098-7654",
"pageviews": 10
}
}
```
```json Event received n°2
{
"transaction_id": "2222-2222-2222-2222",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "tracked_pages",
"properties": {
"tracked_user_id": "1234-5678-9098-7654",
"pageviews": 20
}
}
```
Let's see below the differences between the aggregation types.
## Differences between the aggregation types[](#differences-between-the-aggregation-types "Direct link to heading")
| Aggregation | Code | Units to be charged |
| ---------------- | -------------------------------------------------------- | ------------------- |
| **COUNT** | `COUNT(tracked_pages)` | 2 |
| **SUM** | `SUM(tracked_pages.properties.pageviews)` | 30 |
| **MAX** | `MAX(tracked_pages.properties.pageviews)` | 20 |
| **COUNT UNIQUE** | `UNIQUE_COUNT(tracked_pages.properties.tracked_user_id)` | 1 |
Based on the aggregation type you defined for your Billable metric
`Tracked Pages`, the result that is going to be charged to your customer is
completely different. Make sure to choose the right aggregation type for all
your Billable metrics. If you need help, don't hesitate to reach out the Lago
Team!
# COUNT
The count aggregation type is straightforward. It tallies the exact number of events received during a period.
## COUNT billable metric
Here is how you can create a count aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"count"** as the aggregation type;
5. Apply dimension groups if any; and
6. Click **"Add billable metric"**.
This billable metric is `metered` only, meaning it cannot be recurring, and the number
of billing units resets to 0 at the end of each period.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "API Request",
"code": "api_requests",
"description": "Number of API requests.",
"aggregation_type": "count_agg",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `COUNT(events.code)` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "api_requests",
"properties": {}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "api_requests",
"properties": {}
}
```
In that case, with this aggregation type, Lago simply counts the number events received, **resulting in a billable value of 2 units.**
# UNIQUE COUNT
The unique count aggregation type counts only the unique values of a specified event property.
## UNIQUE COUNT billable metric
Here is how you can create a unique count aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"count unique"** as the aggregation type;
5. Define it this metric is `metered` or `recurring`;
6. Define the property to aggregate;
7. Apply dimension groups if any; and
8. Click **"Add billable metric"**.
This billable metric can be both `metered` or `recurring`.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "API Request",
"code": "api_requests",
"description": "Number of API requests.",
"aggregation_type": "unique_count_agg",
"field_name": "request_id",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `COUNT_DISTINCT(events.properties.property_name)` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "api_requests",
"properties": {
"request_id": "id_1"
}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "api_requests",
"properties": {
"request_id": "id_1"
}
}
```
In that case, with this aggregation type, Lago only counts the unique values `request_id` property in the event payloads, **resulting in a billable value of 1 unit.**
# CUSTOM
**Premium feature ✨**:
This feature is only available to users with a premium license. Please **[contact us](mailto:hello@getlago.com)** to get access this feature.
Lago's basic interface and API allow you to configure metrics using conditional statements and predefined functions for usage aggregation.
However, for more sophisticated metrics, you may require more complex aggregation capabilities than those provided by Lago's default settings.
To address this need, Lago can parse your custom code, enabling you to implement advanced billing rules and custom aggregation logic.
By using custom code for aggregation, you gain complete flexibility over your usage metrics, allowing you to define and tailor them to your specific requirements.
This feature empowers you to create bespoke solutions that precisely match your billing needs.
If you're interested in leveraging custom code aggregation, please contact our team to enable this feature.
# LATEST
The latest aggregation type selects the most recent value of a specified event property from all received events.
## LATEST billable metric
Here is how you can create a max aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"latest"** as the aggregation type;
5. Define the property to aggregate;
6. Apply dimension groups if any; and
7. Click **"Add billable metric"**.
This billable metric is `metered` only, meaning it cannot be recurring, and the number of billing units resets to 0 at the end of each period.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "API Request",
"code": "api_requests",
"description": "Number of API requests.",
"aggregation_type": "latest_agg",
"field_name": "total_requests",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `LAST_VALUE(events.properties.property_name) OVER ([PARTITION BY events.timestamp])` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 20
}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 10
}
}
```
In that case, with this aggregation type, Lago takes the latest value of `total_requests` property from all events, **resulting in a billable value of 10 units.**
# MAX
The max aggregation type selects the highest value of a specified event property from all received events.
## MAX billable metric
Here is how you can create a max aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"max"** as the aggregation type;
5. Define the property to aggregate;
6. Apply dimension groups if any; and
7. Click **"Add billable metric"**.
This billable metric is `metered` only, meaning it cannot be recurring, and the number of billing units resets to 0 at the end of each period.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "API Request",
"code": "api_requests",
"description": "Number of API requests.",
"aggregation_type": "max_agg",
"field_name": "total_requests",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `MAX(events.properties.property_name)` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 20
}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 10
}
}
```
In that case, with this aggregation type, Lago takes the higest value of `total_requests` property from all events, **resulting in a billable value of 20 units.**
# Overview
Aggregation types will define how consumption will be measured.
Here is the full list of **aggregation types** officially
supported by Lago.
| Aggregation | Description | Transcription |
| ---------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **COUNT** | Count the number of times an incoming event occurs | `COUNT(events.code)` |
| **COUNT UNIQUE** | Count the number of unique value of a defined property for incoming events | `COUNT_DISTINCT(events.properties.property_name)` |
| **LATEST** | Get the latest value of a defined property for incoming events | `LAST_VALUE(events.properties.property_name) OVER ([PARTITION BY events.timestamp])` |
| **MAX** | Get the maximum value of a defined property for incoming events | `MAX(events.properties.property_name)` |
| **SUM** | Sum a defined property for incoming events | `SUM(events.properties.property_name)` |
| **WEIGHTED SUM** | Sum a defined property for incoming events, prorated based on time used per period | `SUM(events.properties.property_name) / (DATEDIFF(SECOND, timestamp.event_1, timestamp.event_2) + 1) * (DATEDIFF(SECOND, 'period_start', 'period_end') + 1)` |
| **CUSTOM** | Define a custom code for your aggregation | Custom code |
Except the `COUNT` (that is counting the number of times an event occurs), the
other types aggregate over a single property of the event. **The result of this
aggregation will be used to charge your customers.**
# SUM
The sum aggregation type adds up the value of a defined event property.
## SUM billable metric
Here is how you can create a sum aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"sum"** as the aggregation type;
5. Define it this metric is `metered` or `recurring`;
6. Define the property to aggregate;
7. Apply dimension groups if any; and
8. Click **"Add billable metric"**.
This billable metric can be both `metered` or `recurring`.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "API Request",
"code": "api_requests",
"description": "Number of API requests.",
"aggregation_type": "sum_agg",
"field_name": "total_requests",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `SUM(events.properties.property_name)` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 20
}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "api_requests",
"properties": {
"total_requests": 10
}
}
```
In that case, with this aggregation type, Lago adds up the values of the `total_requests` property in the event payloads, **resulting in a billable value of 30 units.**
# WEIGHTED SUM
The Weighted Sum aggregation type adds up the value of a defined event property and prorates it based on time used per period.
This is especially handy for automated GB/second calculations, for instance.
Currently, prorating is available **per second per period**.
Feel free to reach out if you need additional proration options, such as hourly rates.
## WEIGHTED SUM billable metric
Here is how you can create a weighted sum aggregation from the UI:
1. Access the **"Billable metrics"** section via the side menu;
2. Create a new billable metric;
3. Define a name, a code and an optional description;
4. Select **"weighted sum"** as the aggregation type;
5. Define it this metric is `metered` or `recurring`;
6. Define the property to aggregate;
7. Define the `weighted_interval` used for time proration. Currently, Lago only supports `seconds`.
8. Apply dimension groups if any; and
9. Click **"Add billable metric"**.
This billable metric can be both `metered` or `recurring`.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "GB Seconds",
"code": "gb/s",
"description": "Gigabytes prorated per seconds used per period",
"aggregation_type": "weighted_sum_agg",
"weighted_interval": "seconds",
"field_name": "gb",
"group": {}
}
}'
```
## Calculation example
Lago calculates the `SUM(events.properties.property_name) / (DATEDIFF(SECOND, timestamp.event_1, timestamp.event_2) + 1) * (DATEDIFF(SECOND, 'period_start', 'period_end') + 1)` for the two following events received.
```json
//Event received #1
{
"transaction_id": "transaction_1",
"external_customer_id": "1",
"timestamp": "2022-03-16T00:00:00Z",
"code": "gb/s",
"properties": {
"gb": 20
}
}
//Event received #2
{
"transaction_id": "transaction_2",
"external_customer_id": "1",
"timestamp": "2022-03-17T00:00:00Z",
"code": "gb/s",
"properties": {
"gb": 10
}
}
```
In that case, with this aggregation type, Lago adds up the values of the `gb` property in the event payloads, but prorates it based on time used during the current period.
Keep in mind that the entire month comprises 2,678,400 seconds. The first 20 GB has been used for a day (86,400 seconds), and the 30 GB (20 + 10) has been used for 15 days (1,296,000 seconds till the end of the month):
* (20 / 2678400) x 86400 = 0.64516129032 GB/s
* (30 / 2678400) x 1296000 = 14.5161290323 GB/s
* 0.64516129032 + 14.5161290323 = **15.1612903226 GB/s**
# Create billable metrics
Billable metrics define how incoming events are aggregated in order to measure consumption.
If you want to charge your customers for the use of a particular feature, then
you should create the corresponding billable metric.
To add a new billable metric through the user interface:
* Enter its `name`;
* Assign it a `code` which will be used as the name of the event sent from your
backend;
* Add a `description` *(optional)*;
* Select the `aggregation type` which will define how consumption will be
measured;
* Define the aggregation property `field_name` to aggregate on;
* Define `groups` if you price several dimensions for a same billing component; and
* Define if this billable metric is `recurring` and kept in memory period over period, or resume to 0 at the end of each period.
Here are few examples of billable metrics you can create:
```bash Storage
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "Number of GB used",
"aggregation_type": "sum_agg",
"field_name": "gb",
"recurring": false,
"group": {
"key": "provider",
"value": ["aws", "google", "azure"]
}
}
}'
```
```bash Seats
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Seats",
"code": "seats",
"description": "Active seats added",
"aggregation_type": "unique_count_agg",
"field_name": "seat_id",
"recurring": true
}
}'
```
```bash CPUs
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "CPU",
"code": "cpu",
"description": "Maximum number of CPUs used",
"aggregation_type": "max_agg",
"field_name": "total_cpu",
"recurring": false
}
}'
```
```bash Payments
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Payments",
"code": "payments",
"description": "Card payments issued",
"aggregation_type": "sum_agg",
"field_name": "amount",
"recurring": false
}
}'
```
The next section describes the different
[aggregation types](/guide/billable-metrics/aggregation-types). In addition to this, we have added some
[examples](/guide/billable-metrics/aggregation-types/aggregation-examples) to help you understand the relationship
between incoming events and billable metrics.
# Delete billable metrics
You may delete a billable metric linked to [charges](/guide/plans/charges) associated
with existing [subscriptions](/guide/subscriptions/assign-plan).
If you do so:
* The events associated with this billable metric, which are assigned to the
current billing period or linked to `draft` invoices, will be immediately
deleted;
* The charges associated with this billable metric will be immediately removed
from all plans and existing subscriptions;
* The charges associated with this billable metric will no longer be included in
the [current usage](/api-reference/customer-usage/customer-usage-object) of the customers
concerned; and
* The charges associated with this billable metric will be immediately removed
from all `draft` invoices linked to these subscriptions.
However, the charges associated with this billable metric will still be included
in all `finalized` invoices linked to these subscriptions.
After deleting a billable metric, you can create a new one using the same
code. However, past events will not be linked to this new billable metric.
![How to delete a billable metric](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/images/billable-metrics-delete-68cd9763df888a65237c8f0f5c85358a.png)
```bash Delete "Storage" metric
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request DELETE "$LAGO_URL/api/v1/billable_metrics/storage" \
--header "Authorization: Bearer $API_KEY"
```
# Filters
When setting up your pricing, you may want to filters events according to their property. To do so, you can create filters for your billable metric.
## Create filters[](#create-filters "Direct link to heading")
Your company provides DevOps services and you want to charge your customers for compute capacity by the hour.
In your Lago account, you create a `compute` billable metric that calculates the total number of hours (i.e. `SUM(properties.hours)`).
As your customers can choose from different cloud providers and define a region, you need to filter usage records (i.e. events) according to the provider and region.
On the configuration page of your billable metric, you can define two filters: `provider` and `region`, with all the necessary values (see snippet below).
1. Create a new billable metric;
2. Add a new filter; and
3. Define your different filters.
Here are few examples of billable metrics you can create:
```bash Billable metrics with filters {14-23}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Compute",
"code": "compute",
"aggregation_type": "sum_agg",
"field_name": "hours",
"recurring": false,
"filters": [
{
"key": "provider",
"values": ["aws", "google", "azure"]
},
{
"key": "region",
"values": ["europe", "africa", "asia", "north_america"]
}
]
}
}'
```
Below is an example of an event including two group values for the billable metric described above:
```json Event including a group value
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "event_001",
"external_customer_id": "customer_1234",
"code": "compute",
"timestamp": 1668461043,
"properties": {
"hours": 0.07,
"provider": "aws",
"region": "europe"
}
}
}'
```
Values are case-sensitive. If you don't use the exact value when pushing
events, they will not be taken into account. Following our example: the
expected value is `"aws"` and `"AWS"` is an invalid value.
You can also create billable metrics with dimensions
[via the API](/api-reference/billable-metrics/create).
## Edit filters
You can edit billable metric filters associated with existing subscriptions. It’s important to note that making changes to these metric filters can have an impact on all plans where this billable metric is defined as a charge. Here’s an example to illustrate the impact of editing a billable metric:
```json
From Payload A:
{
"billable_metric": {
"name": "gigabyte",
"code": "gigabyte",
"aggregation_type": "sum_agg",
"field_name": "total",
"filters": [
{
"key": "region",
"values": [
"usa",
"europe",
]
}
]
}
}
To Payload B:
{
"billable_metric": {
"name": "gigabyte",
"code": "gigabyte",
"aggregation_type": "sum_agg",
"field_name": "total",
"filters": [
{
"key": "region",
"values": [
"USA",
"europe",
"africa"
]
}
]
}
}
```
Note that each filter's keys and values are case-sensitive. Here's how Lago handles these changes:
1. Since `"region": "europe"` remains the same between both payloads, this filter remains in the billable metric.
2. As `"region": "usa"` is present in Payload A but not in Payload B, this filter is removed from the billable metric.
3. As `"region": "USA"` is not present in Payload A but is present in Payload B, this filter will be created in the billable metric.
4. Similarly, as `"region": "africa"` is not present in Payload A but is present in Payload B, this filter will be created in the billable metric.
When this billable metric is associated with charges, editing it will impact all plans where it is defined.
* If an existing filter combination remains the same (case 1), Lago will retain this specific filter from the filters combination in all associated charges.
* If an existing filter combination is removed from the billable metric (case 2), Lago will remove this specific filter from the filters combination in all associated charges.
* If a new filter combination is created in the billable metric (case 3 and 4), Lago will not automatically add this filter in the filters combination in all associated charges; you will need to add them manually.
# Recurring vs metered
## Recurring billable metrics[](#recurring "Direct link to heading")
When you set `recurring: true` or choose the "recurring" option in the user interface, the billing aggregation for your billable metric
will persist across billing periods. This means that the accumulated result will carry over and be used to charge the customer in
subsequent periods.
```bash Seats example {14}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Seats",
"code": "seats",
"description": "Active seats added",
"aggregation_type": "unique_count_agg",
"field_name": "seat_id",
"recurring": true
}
}'
```
## Metered billable metrics[](#metered "Direct link to heading")
Conversely, if you set `recurring: false` or select the "metered" option in the user interface, the billing aggregation for your billable
metric will reset to zero at the end of each billing period. This ensures that the customer's charges reflect only the usage within
that specific period.
```bash Storage example {14}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "Number of GB used",
"aggregation_type": "sum_agg",
"field_name": "gb",
"recurring": false
}
}'
```
# Rounding
Lago aggregates your events in real time. You can add rounding rules to the final result.
## Rounding options
When creating or editing a billable metric, you have the option to apply rounding to the final aggregated value. By default, no rounding is applied. If you choose to enable rounding, you can select from the following options:
* **Ceil**: Rounds up to the nearest integer;
* **Floor**: Rounds down to the nearest integer; or
* **Round**: Rounds to the nearest integer based on standard rounding rules.
## Precision types
### No precision
Omitting precision rounds to the nearest whole number (integer). By default, no specific precision is set for your rounding option.
👉 *Example: 123.4567 rounded with no precision → `123`.*
### Positive precision
Adding a positive precision rounds to a specific number of decimal places.
👉 *Example: 123.4567 rounded with precision 2 → `123.46` (two decimal places retained).*
### Negative precision
Adding a negative precision rounds to a specific position to the left of the decimal.
👉 *Example: 123.4567 rounded with precision -1 → `120` (rounds to the nearest ten).*
# SQL Expressions
For more advanced calculations, you can use SQL custom expressions. These expressions are helpful when the aggregation results for a billable metric require complex calculations.
## Creating a SQL Custom Expression
When creating a billable metric, you can choose between using a simple aggregation field or a custom expression.
**Custom expressions allow you to define more advanced computation logic**, which is useful when the required aggregation involves complex calculations that Lago should handle.
To add a custom expression through the user interface:
* Define the `name` and `code` for the billable metric;
* Choose an aggregation type;
* Select `Custom expressions` as the aggregation option instead of `Unique field`;
* Enter your custom expression in the expanded side panel;
* Test the custom expression; and
* Save the billable metric.
Here are few examples of custom expressions you can create for a billable metric:
```bash Storage {13}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "Number of GB consumed",
"aggregation_type": "sum_agg",
"expression": "(event.properties.ended_at - event.timestamp) / 3600",
"field_name": "total",
"recurring": false
}
}'
```
```bash Seats {13}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Seats",
"code": "seats",
"description": "Number of seats used",
"aggregation_type": "unique_count_agg",
"expression": "concat(event.properties.user_id, ‘-‘ , event.properties.app_id)",
"field_name": "total",
"recurring": true
}
}'
```
Custom expressions can be used with any aggregation type except `COUNT`.
## Examples of SQL Custom Expressions
A variety of SQL custom expressions are available for use. Here are a few examples:
* **Concatenation:** `CONCAT(value1, '_', value2)`
* **Math operations:** `((value1 * value2) / value3)`
* **Rounding:** `ROUND(value1 / value2)`
If you need a SQL custom expression that isn't supported by default in Lago, **feel free to contact our team** or **consider contributing to the open-source version**.
## Testing your SQL Custom Expression
Lago provides a testing tool to help you validate the custom expressions you've created. A sample event is used to test your expression. You can override any field in the test event.
If your custom expression is incorrect, Lago will return an error, and you won't be able to save it until it's valid.
Keep the following in mind:
* You can dynamically reference any event field within your expression; and
* Use precise paths to reference fields accurately. For instance, to use the event timestamp, the path is `event.timestamp`. To reference a custom property sent with the event, the path is `event.properties.your_field`.
# Coupons
Coupons allow you to offer discounts to your customers. When you apply a coupon to a customer, its value will be deducted from their next subscription invoice(s).
The value of the coupon is deducted from the amount of the invoice before tax.
## Create a coupon[](#create-coupon "Direct link to heading")
To create a coupon through the user interface:
1. Access the **"Coupons"** section via the side menu;
2. Click **"Add a coupon"**;
3. Choose a name and a code for your coupon;
4. Select the type of coupon (i.e. fixed amount or percentage);
5. Define its value and frequency (i.e. will be applied once, over several
periods or forever);
6. Choose if the coupon can be applied several times to the same customer
account or not;
7. Choose whether or not to set an expiration date (i.e. date after which the
coupon can no longer be redeemed);
8. Select the **plan(s)** or **billable metric(s)** to which the coupon applies (applies to all plans and metrics by default); and
9. Click **"Add coupon"** to confirm.
The expiration date displayed in the app is based on the organization's timezone.
```bash Create a coupon
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/coupons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"coupon": {
"name": "Startup Deal",
"code": "startup_deal",
"amount_cents": 5000,
"amount_currency": "USD",
"coupon_type": "fixed_amount",
"reusable": true,
"frequency": "recurring",
"frequency_duration": 6,
"expiration": "time_limit",
"expiration_at": "2022-08-08T23:59:59Z",
"applies_to": {
"plan_codes": ["premium"],
"billable_metric_codes": []
}
}
}'
```
## Apply coupons[](#apply-coupons "Direct link to heading")
If the currency of the customer is already defined, the currency of the coupon
must be the same, otherwise you will not be able to apply the coupon to the
customer.
To apply a coupon to a customer:
1. Select a customer from the list;
2. Click **"Actions"** in the upper-right corner and select **"Apply coupon"**;
3. Select a coupon;
4. Override values and currency; and
5. Click **"Apply coupon"** to confirm.
You can also apply coupons via the API ([learn more](/api-reference/coupons/apply)).
```bash Apply a coupon to a customer
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/applied_coupons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"applied_coupon": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"coupon_code": "startup_deal",
"amount_cents": 6000,
"amount_currency": "EUR",
"frequency": "recurring",
"frequency_duration": 3
}
}'
```
## Application scope[](#application-scope "Direct link to heading")
You can apply several coupons to a customer. However, if a coupon has been
marked as non-reusable, you will only be able to apply it once to the customer
account, even if it has not been fully consumed. A coupon applied to a customer continues to apply beyond the expiration date.
Coupons are deducted from future subscription invoices. As mentioned previously, the value of
the coupon is deducted from the amount of the invoice before tax.
For coupons whose value is a fixed amount:
* **When the coupon only applies once** and its value is higher than the invoice
amount, the remaining unused amount will be applied to the following invoices,
until the coupon is totally consumed or removed; and
* **When the coupon is recurring** and its value is higher than the invoice amount,
any remaining unused amount will be lost, even if it is the last application
period.
When several coupons are applied to the customer account, they will be deducted according to the following rules:
* **Coupons limited to specific billable metrics will be deducted first** (if any, and if there is at least one subscription
associated with the relevant metric);
* **Coupons limited to specific plans will be deducted next** (if any, and if there is at least one subscription associated with the relevant plan); and
* **Coupons that apply to all plans** will be deducted according to the date on which they were applied (i.e. the coupon that was applied first will be deducted first).
You can see the remaining value / number of remaining periods for each coupon in
the **"Overview"** tab of the customer view.
![Customer account with several coupons](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/images/coupons-remaining.png)
Coupons do not apply to add-ons or any other one-off charges.
## Edit, terminate and delete coupons[](#edit-terminate-and-delete-coupons "Direct link to heading")
In the coupon view, you can click the **ellipsis icon** to see all available
actions:
1. **Edit**: allows you to modify the name, code and settings of the coupon;
2. **Terminate**: allows you to deactivate the coupon so that it cannot be
applied to any new customer (customers to whom the coupon has already been
applied continue to benefit from it); and
3. **Delete**: allows you to delete the coupon and remove it from the list (this
action cannot be undone).
You cannot modify the code, value and frequency of a coupon, or delete it, if
it has already been applied to a customer.
## Remove coupons[](#remove-coupons "Direct link to heading")
To remove a coupon that has been applied to a customer and is still active:
1. Select the customer;
2. Locate the coupon under **"Overview"**;
3. Click the **bin icon** on the right; and
4. Click **"Remove coupon"** to confirm.
The coupon will instantly disappear from the customer view and will not be
applied to the next invoice.
# Credit notes
**PREMIUM FEATURE** ✨
Lago may automatically generate a credit note when a subscription is upgraded or
downgraded. However, only users with a premium license can manually generate
credit notes via the user interface or the API. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
Issue a credit note to refund or credit a `finalized` invoice back to your customer’s account.
Credit notes can be issued for all types of invoices. However, please note that credit notes cannot be issued for prepaid credit purchases that have already been consumed or are linked to a terminated wallet.
## Access credit notes creation flow[](#create-credit-notes "Direct link to heading")
Credit notes can only be issued for invoices with the status `finalized` and
an amount greater than zero.
To create a credit note through the user interface:
1. Go to the **"Customers"** section;
2. Select a customer to open the customer view;
3. Open the **"Invoices"** tab;
4. Click an invoice to see its details; and
5. Select **"Issue a credit note"** from the **"Actions"** dropdown (upper right corner).
The credit note creation process varies depending on the payment status of the
invoice:
* If the payment status of the invoice is `pending` or `failed`, the credit note
will allow you to credit back the customer's account; and
* If the payment status of the invoice is `succeeded`, the credit note will
allow you to credit back the customer's account and/or refund them.
For prepaid credits invoices, credit notes can only be issued for invoices with a `succeeded` payment status. These credit notes are refundable only for this type of invoice and will directly void prepaid credits in the associated wallet.
On subscription invoices, prepaid credits and credit notes applied cannot be refunded. These can only be credited back to the customer's account balance. Coupons are non-refundable and cannot be credited back to the customer's account.
## Issue a credit note
1. Select a reason from the list (e.g. duplicate charge, order cancelation,
etc.);
2. Add an internal note (optional);
3. Select the item(s) and enter the amount(s) you want to credit;
4. Select the credit method(s) (only available for paid invoices -
[learn more](#credit-methods)); and
5. Click **"Issue credit note"** to confirm.
For each item, you must enter a credit amount equal to or less than the
initial amount of the item, excluding tax. The total amount of the credit note
cannot exceed the total amount of the invoice.
```bash Create a credit note
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/credit_notes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"credit_note": {
"invoice_id": "**LAGO_INVOICE_ID**",
"reason": "duplicated_charge",
"credit_amount_cents": 10,
"refund_amount_cents": 5,
"items": [
{
"fee_id": "__LAGO_FEE_ID__",
"amount_cents": 10
},
{
"fee_id": "__LAGO_FEE_ID__",
"amount_cents": 5
}
]
}
}'
```
When the credit note is created, it will appear below the original invoice on
the invoice details page and in the **"Credit notes"** tab of the customer view.
In addition to this, a `credit_note.created` [webhook](/api-reference/webhooks/messages)
will automatically be sent by Lago.
You can link several credit notes to an invoice. Like invoices, credit notes
have a unique number and can be downloaded in PDF format.
## Credit methods[](#credit-methods "Direct link to heading")
### Refund[](#refund "Direct link to heading")
When a credit note involves a refund, the amount of the refund will be included in the `credit_note.created` [webhook](/api-reference/webhooks/messages), which allows you to proceed with the payment.
The credit note will also contain a `refund_status` field, which can be set to `pending`, `succeeded`, or `failed`. You can update the refund status via the API.
Refunding a prepaid credit invoice will automatically void the corresponding prepaid credits in the active wallet.
If you use one of our native payment integrations, the refund process will
automatically be triggered by Lago.
### Credit note wallet[](#credit-note-wallet "Direct link to heading")
The amount of the credit note that is not refunded is credited to the customer's
account via a credit note wallet. The credit amount is included in the
`credit_note.created` [webhook](/api-reference/webhooks/messages) and displayed on the
credit note details page.
A credit note wallet is linked to a single credit note and therefore, to a
single invoice. If there are several credit notes linked to the customer's
account, Lago will create a credit note wallet for each of them.
Credit note wallets are different from wallets associated with [prepaid credits](/guide/wallet-and-prepaid-credits).
The total amount available in the credit note wallets will be deducted from the
subtotal of the customer's next invoice(s), after tax (see below).
```
## EXAMPLE OF INVOICE
All subscriptions = $50
All usage-based fees = $20
Coupons = $10
---
Subtotal (excl. tax) = $60
Tax (10%) = $ 6
---
Subtotal (incl. tax) = $66
Credit notes = $20
Prepaid credits = $30
---
Total due = $16
```
When the credit note wallet is created, the initial `credit_status` is
`available`. Then when the amount of the credit note wallet is zero, the status
switches to `consumed`.
## Void available credit[](#void-credit-note "Direct link to heading")
You can void the available credit linked to a specific credit note. To do so:
1. Go to the **"Customers"** section;
2. Select a customer to open the customer view;
3. Open the **"Credit notes"** tab;
4. Click a credit note to see its details; and
5. Select **"Void credit available"** from the **"Actions"** dropdown (upper
right corner).
When voiding a credit note wallet, the remaining credit amount will be lost
and the `credit_status` will switch to `voided`. This action cannot be
canceled.
```bash Void a credit note
LAGO_URL="https://api.getlago.com"
CREDIT_NOTE_ID="__YOU_CREDIT_NOTE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/credit_notes/$CREDIT_NOTE_ID/void" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
# Customer management
## Create and update a customer[](#create-and-update-a-customer "Direct link to heading")
To create a customer through the user interface:
1. Access the **"Customers"** section via the side menu;
2. In the upper right corner, click **"Add a customer"**;
3. Enter the customer's name and external ID (i.e. unique ID as defined in your
backend system);
4. Select the customer's timezone (optional -
[learn more](/guide/customers/invoice-customer#bill-following-your-customers-timezone));
5. Enter the customer's billing information, including company information and
address (optional);
6. Select the default payment provider for this customer (optional -
[learn more](/guide/payments/overview)); and
7. Click **"Create customer"** to confirm.
```bash Create or update a customer
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "EUR",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"tax_codes": [],
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
}
"metadata": [
{
"key": "Name",
"value": "John",
"display_in_invoice": true
}
]
}
}'
```
Once a customer is created, you can access the customer view, where you can edit their information.
You cannot change the `external_id` and the `currency` of customers after an object has been
assigned to them (i.e. plans, coupons, one-off invoices, wallet and credits).
## Companies vs Individuals
When creating or updating a customer, you can specify whether the customer is a `company` or an `individual` by setting the customer type.
By default, if no customer type is specified, the customer will be created without a defined type, and you will need to assign one manually.
## Assign objects to a customer[](#assign-objects-to-a-customer "Direct link to heading")
The usage monitoring and billing processes start when you assign a plan to a
customer, which triggers a [subscription](/guide/subscriptions/assign-plan).
You can also apply [coupons](/guide/coupons), [one-off invoices](/guide/one-off-invoices/create-one-off-invoices) and
[prepaid credits](/guide/wallet-and-prepaid-credits) to a customer account.
To assign objects to a customer through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the upper right corner of the customer view, click **"Actions"**; and
4. Select an action from the dropdown list.
## Monitor the customer's current usage[](#monitor-the-customers-current-usage "Direct link to heading")
When a plan that includes usage-based charges is assigned to a customer, you can
start pushing [events](/guide/events/ingesting-usage) associated with the customer account.
During the billing period, the customer's current usage is visible in the
**"Analytics"** tab of the customer view, under **"Current usage report** including (but not limited to):
* Total amount for the period under consideration; and
* Breakdown by charge, including total number of billing units and amount.
You can retrieve the customer's current usage via the API using [this endpoint](/api-reference/customer-usage/get-current).
```bash Get customer current usage
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_CUSTOMER_ID="5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba"
EXTERNAL_SUBSCRIPTION_ID="sub_1234567890"
curl --location --request GET "$LAGO_URL/api/v1/customers/$EXTERNAL_CUSTOMER_ID/current_usage?external_subscription_id=$EXTERNAL_SUBSCRIPTION_ID" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
## Monitor the customer's billing status[](#monitor-the-customers-overdue-balance "Direct link to heading")
The "**Billing overview**" lets you see in a glance where a customer stands in terms of revenue and collection. It takes into account invoices since the customer's creation date.
* Gross revenue indicates how much has been billed to this customer
* Total overdue highlights the aggregated amount from invoices that are past due
You can retrieve the customer's gross revenue via the API using [this endpoint](/api-reference/analytics/gross-revenue).
```bash Get customer gross revenue
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/gross_revenue?external_customer_id=hooli_1234¤cy=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
You can retrieve the customer's overdue balance via the API using [this endpoint](/api-reference/analytics/overdue-balance).
```bash Get customer overdue balance
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request GET "$LAGO_URL/api/v1/analytics/overdue_balance?external_customer_id=hooli_1234¤cy=USD" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
```
## Deleting a customer
You may delete a customer linked to existing objects (i.e. applied coupons, wallets, subscriptions, add-ons).
If you do so:
* All [subscriptions](/guide/subscriptions/assign-plan) associated with this customer account will be immediately terminated (this action may trigger the generation of invoices and/or credit notes);
* All [coupons](/guide/coupons) applied to this customer account will be immeditely terminated;
* The customer's active [wallet](/guide/wallet-and-prepaid-credits) will be immediately terminated and all remaining credits will be voided; and
* All `draft` invoices associated with this customer account will be immediately finalized.
`finalized` invoices and [credit notes](/guide/credit-notes) associated with the deleted customer remain available in the **"Invoices"** section of the user interface and can also be retrieved via the API.
It is possible to generate new credit notes and process refunds after the deletion of the customer.
After deleting a customer account, you can create a new one using the same `external_id`.
# Customer metadata
## Add metadata on customer
Metadata on customer is useful for storing additional structured information on an object to provide more context.
For example, you could store a customer's full name and unique identifier from your system on a Customer object by defining a key-value pair. A key cannot exist without its corresponding value, and vice versa.
## Edit and delete metadata on customer
After adding metadata to a customer, you can edit or delete it. To edit metadata, you have two options:
1. Use the user interface to update the information displayed in the "Edit customer" drawer, and then save the customer changes.
2. Use the API to target the key-value pair information with the metadata ID in your code snippet and edit the key and value.
When editing customer metadata through the API, make sure to include the existing metadata in your payload to avoid removing them.
Similarly, you can delete a key-value metadata pair by:
1. Clicking on the trash icon in the user interface, and then saving the customer changes.
2. Removing the key-value metadata object from your code snippet when using the API.
## Display metadata in invoice object
To display customer metadata on invoices, you can switch on the option in the customer creation/edition drawer or set `display_in_invoice` to true. Once this option is activated, metadata will be displayed on all new finalized and downloaded invoices.
When the customer's metadata is added/edited/removed, the change only applies to new PDF files. Existing documents are not affected.
## Customer metadata limitiation
1. We are limiting the number of metadata on customers to 5.
2. Keys must be strings under 20 characters.
3. Values must be strings under 40 characters.
# The customer portal
The Lago Customer Portal is a user-friendly platform that allows you to effortlessly share billing information, such as past invoices, with your end customers. As we continue to develop this tool, you will be able to display even more useful information to your customers.
## Generate a customer portal link
To generate a customer portal URL that can be embedded into your product, you have two options:
1. Use the [API endpoint](/api-reference/customers/customer-portal); or
2. Click the Customer Portal link on a specific customer details view.
## Embedding the dashboard
You can also use the API to generate an embeddable Customer Portal that can be displayed in your application by using an iframe. To do so, use the endpoint `/customers/:external_customer_id/portal_url` to generate an embeddable URL that can be displayed in your user interface.
For security reasons, the token returned by the API **expires after 12 hours**. Therefore, it is important to use the endpoint and generate a new token every time a customer refreshes or accesses the billing page.
## Customer portal preferred language
By default, the embedded portal is displayed in English. However, you can easily change the language for a specific customer by adjusting the `document language` in their settings. To access this feature, follow these simple steps:
To access document language settings:
1. Go to the specific customer's profile;
2. Click the **Settings** tab;
3. **Edit** the document language section; and
4. Select the preferred language.
You can also update the language of a customer directly from the API.
If the language you are looking for is not yet available, please [visit this page](/api-reference/resources/locales).
## Customer portal information
### 1. Invoice history
The invoice history section provides a summary of both total invoices (everything that has been invoiced since the beginning) and overdue invoices (all the invoices past their due date, which are due). Your customers can know where they stand in one glance.
The Customer Portal allows your customers to retrieve all past invoices and download them with ease. Lago displays useful billing information such as the issuing date, invoice number, amount, and payment status (paid or unpaid). Additionally, your customers can filter the list and search for a specific invoice.
### 2. Customer information
In addition to viewing their invoice list, customers can retrieve essential billing information, including legal name, tax identification number, billing email, and billing/shipping addresses.
Customers can also update this information directly through the portal, ensuring that their billing details remain synchronized with the latest data.
### 3. Plans and usage information
In addition to viewing their invoices and customer details, customers can access their subscriptions and usage directly through the portal.
For subscription details, they can view key information such as the plan name, recurring fee, and subscription renewal date.
Customers also have real-time access to comprehensive usage details, including:
* Total lifetime usage and the next threshold for subscriptions using progressive billing;
* A detailed usage report, showing the number of units consumed and associated costs; and
* A full breakdown of usage by billing filters and groups.
### 4. Prepaid credits information
The customer portal provides your customers with real-time access to their prepaid credit balance, showing the remaining credits based on their current usage.
Additionally, customers can top up their paid credits, ensuring their wallet is always sufficiently funded.
# Invoice a customer
If a customer has an active subscription, Lago will automatically generate an [invoice](/guide/invoicing/overview) for them at the end of the billing period.
## Bill following your customer's timezone
**Premium feature ✨**:
The timezone feature is only available to users with a premium license. Please **[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago Self-Hosted Premium.
The beginning and end of the billing period depend on the timezone applied to the customer account. The default timezone is UTC but you can define another timezone for your organization, which can be overwritten by the customer's timezone.
To set the customer's timezone through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab of the customer view, click **"Edit"** above the customer details;
4. Select a timezone from the list; and
5. Click **"Edit customer information"** to confirm.
You can define a specific timezone by using the `timezone` field on a customer.
```bash Set a customer timezone {23}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "EUR",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
"vat_rate": 12.5
},
"metadata": [
{
"key": "Name",
"value": "John",
"display_in_invoice": true
}
]
}
}'
```
The dates displayed in the **"Usage"**, **"Invoices"** and **"Credit notes"** tabs of the customer view are based on the customer's timezone.
You can hover over any date in the customer view to see the reference timezones.
## Preferred language
The default language for documents is defined at the organization level ([learn more](/guide/invoicing/download-invoices#translate-invoices)). It can be overwritten at the customer level.
To set the customer's preferred language:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. Open the **"Settings"** tab;
4. Click **"Add a language"**;
5. Select a language from the list; and
6. Click **"Add language"** to confirm.
You can define a specific preferred language by using the `document_locale` field on a customer, inside the `billing_configuration` object.
```bash Set a customer preferred language {32}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "EUR",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
"vat_rate": 12.5
},
"metadata": [
{
"key": "Name",
"value": "John",
"display_in_invoice": true
}
]
}
}'
```
Please refer to the API documentation to see the [list of supported languages](/api-reference/resources/locales).
When the customer's preferred language is updated, the change only applies to new PDF files. Existing documents are not affected.
# Automatic dunning
Automate how to communicate with your customers to remind them of overdue invoices and attempt to recover their overdue balance using dunning campaigns.
**PREMIUM ADD-ON** ✨
This feature is available upon request only. Please **[contact us](mailto:hello@getlago.com)** to get access to this premium feature.
## Create campaigns
Automatic dunning relies on the concept of dunning campaign, which then can be applied at the organization level, or per customer. You can create several campaigns to accommodate different needs: different thresholds or different cadences for instance. The goal of a campaign is to collect payment for a customer's overdue balance.
Follow these steps to create a new campaign
1. Access the dunning settings page through the **Settings** section > **Dunning** tab;
2. In the **Dunning campaigns** section, click **“Add”** to create a new campaign;
### Campaign settings
These settings allow you to identify a campaign.
1. Enter its **`name`**;
2. Assign it a unique **`code`** (i.e. unique ID as defined in your backend system); and
3. Add a **`description`** *(optional).*
### Trigger settings
These settings define when a campaign should start running for a customer.
4. Define an **`overdue balance threshold`.**
At least one threshold is required to be able to save a campaign.
You can define as many thresholds as currencies you support. When a dunning campaign applies to a customer, as soon as they reach this threshold, the campaign will launch for this customer.
If a customer is invoiced in a currency that you don't support in your dunning campaign, they won't be eligible to this dunning campaign.
### Attempt settings
5. You can **`preview the email`** sent in case no payment provider is linked, or if the payment from an attempt fails.
6. Add **`a delay between attempts`,** in days.
The first attempt of a dunning campaign will happen when the overdue balance threshold is met. The next attempts will be triggered after the delay you have set.
7. Decide to **`End the flow after`** a number of attempts.
### Default campaign for your organization
8. You can choose to **`Set as default campaign for your organization`**.
## Automatic dunning at the organization level
When defining a default campaign at the organization level, the campaign will apply to all customers inheriting the organization dunning behavior, except those for whom:
* a specific campaign has been applied,
* dunning has been deactivated.
It is possible to have no campaign defined as default for the organization, and apply dunning campaigns independently to each customer.
This setting is also available from the list of dunning campaigns, from where you can directly set a campaign as default for the organization.
## Automatic dunning at the customer level
If a campaign has been set as default for the organization, by default it will apply to all customers. You can chose to override this behavior at the customer level.
1. Access the customer settings page through the **Customer** details page > **Settings** tab;
2. In the **Dunning** section, click **“Edit”** to change the dunning behavior;
3. Select the behavior you want to apply.
### Fallback to default dunning behavior from organization
The behavior defined at the organization level will prevail: either a campaign is applied, or no dunning is set.
### Apply a specific campaign for a customer
Only the campaigns with a threshold defined in the customer's currency are available.
The campaign will apply as soon as the behavior is saved, and the customer will no longer listen to what has been defined at the organization level.
#### Deactivate dunning
No automatic dunning attempt will impact this customer, whether it is the default organization campaign or a campaign applied at the customer level.
You can still trigger manual duning requests for the customer.
### Change from one campaign to another
If you change the default campaign to apply another, or if you change the campaign applied to a customer, dunning could running for some customers. In that case the current campaign will be stopped, and the new campaign will take precedence and start from zero.
## Behavior of a campaign
Once a campaign is applied to a customer:
1. Its threshold will be monitored.
2. When the customer's overdue balance reaches the threshold, a first payment request will be triggered during the coming hour. Depending if a payment provider is available for the customer or not, a payment intent and/or an email will be triggered.
3. If a second attempt is planned, after the defined delay the overdue balance will be checked again. If still above the threshold, a new attempt will be triggered. New attempts will be triggered this way until the maximum number of attempts defined is reached.
4. If reaching the end of the planned attempts, the dunning campaign will be considered as completed. No further attempts will be triggered, unless the campaign applied to the customer is changed.
### A payment provider is connected for the customer
A payment intent will be generated for the amount shown.
* If the payment fails, and email will be sent requesting payment, with a URL to pay (except for Gocardless where no payment URL is provided).
* When the payment is successful, the attached invoices will automatically be updated with a succeeded payment status.
### No payment provider is available for the customer
An email will be sent requesting payment for the overdue balance.
* When the payment is successful, you will have to manually update the payment status of said invoices.
# Manual dunning
Dunning refers to the process of communicating with customers to remind them of overdue invoices and attempt to recover the outstanding amounts.
## Overdue balance payment
When a customer has some invoices past their due date, their [overdue balance](https://docs.getlago.com/guide/customers/customer-management#monitor-the-customers-billing-status) becomes positive, and you have the ability to request its payment manually.
**Premium feature ✨**
This feature is only available to users with a premium license. Please **[contact us](mailto:hello@getlago.com)** to get access access to Lago Cloud and Lago Self-Hosted Premium.
In the customer view, a "request payment” link appears within the overdue balance warning.
By clicking on it, a panel opens so you can:
* Review the invoices included in the overdue balance,
* Review the email which will be sent in case the payment fails, or if no payment provider is linked
* Confirm you want to request the payment.
You can create a payment request for the overdue balance from the API, targeting the invoices you want to be paid.
```bash Create a payment request
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/payment_requests/" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
{
"payment_request": {
"lago_invoice_ids": ["4064eff9-e7a6-4692-a289-15d7d5da9b83", "b1f36d2f-8ea6-4192-9407-8e87ba5c28c2"],
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"email": "rebecca@piedpiper.test"
}
}'
```
## A payment provider is connected for this customer
A payment intent will be generated for the amount shown.
* If the payment fails, and email will be sent requesting payment, with a URL to pay (except for Gocardless where no payment URL is provided).
* When the payment is successful, the attached invoices will automatically be updated with a succeeded payment status.
## No payment provider is available for this customer
An email will be sent requesting payment for the overdue balance.
* When the payment is successful, you will have to manually update the payment status of said invoices.
# Emails
Send automatic emails when issuing an invoice or any billing documents.
**PREMIUM FEATURE** ✨
Only users with a premium license can automatically send emails from Lago to their customers. Please **[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago Self-Hosted Premium.
With Lago, sending invoices and credit notes to your customers is simple - you can automatically email them as soon as they are created.
Lago will never ask for payment details or personal information.
## SMTP setup on Lago Cloud
You don't have to worry about SMTP settings with Lago, we take care of it, so you can sit back and relax.
## SMTP setup on Lago Self-hosted Premium
In order to use the email feature, please configure your environment variables [as described here](/guide/self-hosted/docker#smtp-configuration).
## Prerequisites for sending emails
To send emails to your customers, you will need to:
1. Define an organization email in Settings > Organization;
2. Optionally, add your organization’s logo in Settings > Organization;
3. Turn on the relevant email scenarios; and
4. Define the customer’s email address during customer creation/edition.
5. To send invoices to multiple recipients, define multiple email addresses at the customer level, separated by commas.
(e.g. `billing@acme.com`,`accounting@acme.com`,`finance@acme.com`)
## Email scenarios
Lago sends emails to your customers in two scenarios: when an invoice is finalized (i.e. subscription invoices, one-off invoices, invoices related to credit purchases), and when a credit note is issued for a customer.
By default, both scenarios are switched off. To turn these scenarios on/off:
1. Go to Settings;
2. Open the Emails tab;
3. Toggle each scenario on/off; or
4. Click on a scenario to see the corresponding email; and
5. Use the toggle in the upper-right corner to switch this scenario on/off.
To avoid sending too many notifications to customers, we have deactivated emails for invoices without fees.
Although invoices with `"fees_amount_cents": 0` are not sent to customers by email, they are available in the database and user interface.
## Email locale
The content of the email will be based on the organization or customer's document locale. This means that the email will have the same locale as the invoice sent.
## Email sending address
For the cloud version, Lago uses [no-reply@getlago.com](mailto:no-reply@getlago.com) as the sending email address. Any responses from your customers will be directed to the email address you have established for your organization in the organization settings.
## Email template
As mentioned above, some information in the email template can be customized based on the settings of your account, including:
1. The logo of your organization;
2. The name of your organization; and
3. The email address of your organization.
# Entitlements
Lago partners with [Oso](https://osohq.com) to provide the best-in-class Entitlements solution.
[Oso](https://www.osohq.com/) is an authorization-as-a-service provider partnering with Lago to offer entitlements. You can use either the open-source version (available on [Github](https://github.com/osohq/oso)) or the cloud-hosted version. To create entitlements with Lago, you must open an account on Oso.
Oso offers a suitable solution for Entitlements. For more information, please refer to [Oso's documentation](https://www.osohq.com/docs/guides/model/entitlements).
## Define available features and plan's quota
First, define the available features for each plan. For instance, the Basic plan has a limited set of features, while the Premium plan offers the full range.
In addition to this, you can use Lago to bill metering and overage. This information can then be passed directly to Oso's `plan_quota` and `quota_used` to limit usage for a specific feature.
## Example
[Oso's documentation](https://www.osohq.com/docs/guides/model/entitlements) explains the following example of entitlements properly.
```ruby
actor User { }
resource Organization {
roles = ["admin", "member"];
permissions = ["create_repository"];
"member" if "admin";
}
resource Plan {
roles = ["subscriber"];
relations = { subscribed_organization: Organization };
"subscriber" if role on "subscribed_organization";
}
resource Feature {
relations = { plan: Plan };
}
declare plan_quota(Plan, Feature, Integer);
declare quota_used(Organization, Feature, Integer);
plan_quota(Plan{"pro"}, Feature{"repository"}, 10);
plan_quota(Plan{"basic"}, Feature{"repository"}, 0);
has_quota_remaining(org: Organization, feature: Feature) if
has_quota(org, feature, quota) and
quota_used(org, feature, used) and
used < quota;
has_quota(org: Organization, feature: Feature, quota: Integer) if
plan matches Plan and
has_relation(plan, "subscribed", org) and
plan_quota(plan, feature, quota);
has_permission(user: User, "create_repository", org: Organization) if
has_role(user, "member", org) and
has_quota_remaining(org, Feature{"repository"});
test "members can create repositorys if they have quota" {
setup {
quota_used(Organization{"apple"}, Feature{"repository"}, 5);
quota_used(Organization{"netflix"}, Feature{"repository"}, 10);
quota_used(Organization{"amazon"}, Feature{"repository"}, 0);
has_relation(Plan{"pro"}, "subscribed", Organization{"apple"});
has_relation(Plan{"pro"}, "subscribed", Organization{"netflix"});
has_relation(Plan{"basic"}, "subscribed", Organization{"amazon"});
has_role(User{"alice"}, "member", Organization{"apple"});
has_role(User{"bob"}, "member", Organization{"netflix"});
has_role(User{"charlie"}, "member", Organization{"amazon"});
}
assert has_quota_remaining(Organization{"apple"}, Feature{"repository"});
# Apple has quota remaining, so all good
assert allow(User{"alice"}, "create_repository", Organization{"apple"});
# Netflix has used all quota
assert_not allow(User{"bob"}, "create_repository", Organization{"netflix"});
# Amazon doesn't have any quota left
assert_not allow(User{"charlie"}, "create_repository", Organization{"amazon"});
}
```
# Events list
By ingesting events, you can see them flowing in the Lago application by using the events list. It allows you to take a deeper look at ingested events and detect possible warnings.
## Accessing the events list[](#accessing-the-events-list "Direct link to heading")
You can access the events list from the UI by following this path:
1. Go to the **Developers** section in the sidebar;
2. Click the **events** tab;
3. See a list of ingested events; and
4. Reload this list when you ingest new events.
By default, the UI shows you a list of the latest 20 events, but you can load
much more by scrolling down the page.
If an event is not shown in the UI, it has **not** been ingested.
## Accessing a specific event[](#accessing-a-specific-event "Direct link to heading")
In the events list view, by clicking on a specific event, you will have access to 2 main
blocks:
1. **A list of useful properties returned**
* **Time:** timestamp of the received events;
* **Customer ID:** the ID of your customer;
* **Billable metric code:** code of the billable metric linked to the event;
* **Billable metric name:** name of the billable metric linked to the event;
* **Transaction ID:** unique `transaction_id` of the event used as
idempotency key;
* **IP Address:** IP address of the event sender; and
* **Client API:** Lago Client API used to send the event.
2. **A JSON with event's arguments sent in the payload**
## Possible warnings[](#possible-warnings "Direct link to heading")
Some events can be ingested but triggering a bad or unexpected behavior. This is
why Lago displays in the UI two possible warnings:
1. The event `code` is **not related to an existing billable metric**; and
2. The billable metric's **property used for the aggregation is not sent**
through this event.
# Ingesting usage
This guide explains how Lago ingests usage-based events coming from your application.
## Define a billable metric[](#define-a-billable-metric "Direct link to heading")
**Usage events are designed to target very specific
[billable metrics](/guide/billable-metrics/create-billable-metrics) created from the UI**. If you don't understand the
concept of billable metrics, we recommend you to read it first.
First things first, you need to define a billable metric from the UI to send
usage measurement events:
1. In the Lago app, go to the **"Billable metrics"** section;
2. Click **"Add a billable metric"**;
3. Add metric information, including:
* `name`
* `code` (used to send events via API)
* `description` (optional)
4. Define whether or not this metric is `recurring`; and
5. Choose an aggregation type to define how usage should be calculated.
Billable metrics represent the features of your product. Events should automatically be sent to Lago by your application
based on your customers' actions.
## Send usage measurements to Lago[](#send-usage-measurements-to-lago "Direct link to heading")
To send usage events to Lago, you need to use the **Lago API**. A measurement
event is JSON with the following fields:
```json
{
"transaction_id": "__TRANSACTION_ID__" // (Required) Unique identifier of the event
"external_subscription_id": "__SUBSCRIPTION_ID__" // (Required) Unique identifier of your customer's subscription
"code": "__EVENT_CODE__", // (Required) The billable metric's code
"timestamp": 1650893379, // (Required) UNIX timestamp of the event
"precise_total_amount_cents": "140", // (Optional) Precise amount cents of the event used for dynamic charge model
"properties": {
"custom_field": 12, // (Optional) Custom variables defined as properties
"operation_type": "add" or "remove" // (Optional) Required only for recurring metric based on the unique count aggregation
}
}
```
The `transaction_id` is very useful to ensure the uniqueness of the events
received. It is mandatory to define on your own a unique `transaction_id` for
each event you send to Lago.
This identifier is used to deduplicate events ingested, making sure we don't
ingest twice the same event (otherwise, this could create billing errors for
your customers).
* If a `transaction_id` is new to Lago, the event is ingested;
* If a `transaction_id` has already been received by Lago, it's ignored.
**Good practice:**
Send the id of the transaction coming from your backend.
If you do not have an existing id for a transaction, you can create a unique one
by concatenating the `code` of the Billable metric and the `timestamp` of the
event \*(example: `api_searches_2022-04-01T03:49:23Z`).
This attribute allows Lago to assign the event to the right subscription (and therefore to the right customer).
The `external subscription_id` is required, as it ensures accurate billing.
The event `code` represents the unique code of the Billable metric you want to
start ingest measurements on. This code is required for all events received in
Lago. For instance, you can start ingesting events for Billable metrics with
codes `api_seaches` *(for api products example)*, `storage` *(cloud companies
example)*, `atm_withdrawals` *(fintech example)*, or anything you need to define
as a paying feature.
The event timestamp is the date when the billing event occurs in your
application and sent to Lago. This event must be a
**[UNIX Timestamp](https://www.unixtimestamp.com/).** For instance, you could
define `1650893379` for *Mon Apr 25 2022 13:29:39 GMT+0000* or `1651682217`for
*Wed May 04 2022 16:36:57 GMT+0000*.
**This `timestamp` is not mandatory to send the event**. If you do not specify a
timestamp on your own, Lago automatically defines the reception date of the
event as the event timestamp.
The event’s precise amount in cents refers to the amount sent to Lago when using a dynamic charge model.
This value must be specified in cents.
**The precise\_total\_amount\_cents is not mandatory when sending the event.** If you do not specify an amount, Lago will automatically set it to 0, and the event will not be included in the charge aggregation.
Event properties are useful to send more context in usage events. Moreover, they
are also very useful when you need to aggregate a Billable metrics for `SUM`,
`MAX` and `UNIQUE COUNT`. Event properties can be `strings`, `integers`,
`floats`, `uuids` or `timestamps`.
In case of an aggregation type `UNIQUE COUNT` for a metric that is `recurring`
, the `operation_type` is required.
By sending `add`, you will add a value. By sending `remove`, you will remove a value.
If you were using the `external_customer_id` to send usage measurement, note
that this field is deprecated and is no longer supported or maintained. Please
use the `external_subscription_id` instead.
## Idempotency and retries[](#idempotency-and-retries "Direct link to heading")
By using a unique `transaction_id`, can send events to Lago as much as you want
without worrying about sending twice the same event. Duplicates will be ignored
by our system. This ensures that your customers' usage is counted once. In case
of duplicates, we guarantee that only one of the events will be ingested, and
the other ones are ignored.
In case you are not sure if an event has been ingested, we recommend you to send
it multiple times (or to replay it). Once again, with the uniqueness of the
`transaction_id`, your customers won't be badly affected.
## User action trigger or periodic trigger[](#user-action-trigger-or-periodic-trigger "Direct link to heading")
With Lago, you can define when you need to trigger events based on the actions
your customers make in your application. There are 2 ways of tracking billing
events with Lago.
### User action trigger[](#user-action-trigger "Direct link to heading")
Anytime a user perform an action in your product, this sends an event to Lago.
This can be useful for companies tracking usage with a lot of granularity. As we
do the math for you, you can send events whenever you need and don't compute
hard calculations on your own.
For instance, think of a *fintech company* tracking user action. Each time a
customer withdraw money at an ATM, you send an event to Lago. We aggregate the
usage of a billable period based on what you defined in a Billable metric called
`atm_withdrawals`.
### Periodic trigger[](#periodic-trigger "Direct link to heading")
Some companies, such as infrastructure or cloud ones, often use periodic
triggers to calculate consumption. Think of the example of a thermometer to
measure fever. We would probably track the temperature once per hour (at a
periodic time). This is the same for cloud companies selling computation. You
could send an event to Lago each single minute measuring the CPU consumption of
a customer.
## Batching events
In Lago, event batching allows for the efficient ingestion of multiple events through a single API call.
This capability enhances data throughput and reduces the number of API requests needed for event management.
* **Batching multiple events:** Users can aggregate multiple events into a single batch. This consolidation enables the ingestion of numerous events simultaneously, significantly optimizing the data transmission process.
* **API call limitation:** Lago supports batching of up to 100 events per API call. This feature is designed to balance between high-volume data handling and system performance.
* **Validation process:** If any event within the batch does not meet the structural requirements, the entire batch will be rejected. This ensures data integrity and consistency. Users are advised to verify the structure of each event before batching to prevent rejections.
## Designed for flexibility[](#designed-for-flexibility "Direct link to heading")
Lago is designed to ingest a high number of events. By defining aggregation
rules, you can define any billing use cases your company might want to track.
Whether you need to send **[user action triggered](#user-action-trigger)**
events or **[periodic triggered](#periodic-trigger)** events, Lago does the math
on your own so you don't have to query heavy databases before charging your
customers.
## Next steps[](#next-steps "Direct link to heading")
Once you defined your Billable metrics (with their aggregation rules), and
started ingesting events to track usage, you are able to define how much your
customers will pay for it. This has to be specified in
**[Plans](/guide/plans/overview)**.
# Metering ingestion sources
Here is a list of sources you can use to ingest usage data. Some of these sources are capable of handling up to 15,000 events per second with default settings.
## Free sources
Here is the list of usage ingestion and metering sources available in the free version of Lago.
Establishes a connection to a server and continuously sends requests for a specific message.
## Premium sources
Here is the list of usage ingestion and metering sources available in the premium version of Lago.
Receives messages from multiple Kinesis streams.
Fetches objects from an S3 bucket, with optional prefix filtering, either by listing items or through real-time upload notifications.
Retrieves and processes messages from an AWS SQS queue using a specified URL.
Transmits usage and metering data via Azure CosmosDB, Queue Storage, or Table Storage.
Monitors a CockroachDB Core Changefeed and creates a message for each received row.
Reads data from one or more CSV files
Transmits usage and metering data via GCP Big Query or Cloud Storage bucket.
Establishes a connection to Kafka brokers and consumes messages from one or more topics.
Runs a query in MongoDB and produces a message for every document returned.
Transmits usage and metering data via Redis Scan or Streams.
Transmits usage and metering data via SQL raw or select.
Establishes a connection to a websocket server and continuously send usage for incoming messages.
# Retrieving usage
Learn how to retrieve usage data for both current and past billing periods.
## Retrieve current usage
Current usage fetches real-time customer data for the open billing period.
Keep in mind that since this period isn't closed yet, invoice details may evolve over time.
```bash Retrieve current usage
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_CUSTOMER_ID="__EXTERNAL_CUSTOMER_ID__"
EXTERNAL_SUBSCRIPTION_ID="__EXTERNAL_SUBSCRIPTION_ID__"
curl --location --request GET "$LAGO_URL/api/v1/customers/$EXTERNAL_CUSTOMER_ID/current_usage?external_subscription_id=$EXTERNAL_SUBSCRIPTION_ID" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
## Retrieve past usage
Retrieving historical customer usage data provides usage details for closed billing periods.
This data remains unchanged unless you're in a grace period, where past usage can be adjusted for a draft invoice.
```bash Retrieve past usage
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_CUSTOMER_ID="__EXTERNAL_CUSTOMER_ID__"
EXTERNAL_SUBSCRIPTION_ID="__EXTERNAL_SUBSCRIPTION_ID__"
curl --location --request GET "$LAGO_URL/api/v1/customers/$EXTERNAL_CUSTOMER_ID/past_usage?external_subscription_id=$EXTERNAL_SUBSCRIPTION_ID" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
# Integration testing
This step-by-step integration guide will help you get started with Lago.
## Foreword[](#foreword "Direct link to heading")
At the moment, each Lago account is associated with a unique environment. It is
currently not possible to have your test environment and production environment
in the same account.
However, we can suggest different workarounds:
1. **Create two accounts** to get access to two environments, one that could be
called "Company Staging" and another one that could be called "Company
Production"; or
2. **Leverage our two hosting solutions** to use Lago Cloud as a test
environment and Lago Open Source as a production environment (or vice versa).
Please note that the above workarounds will require you to replicate the same
setup in both environments.
In the future, you will be able to get access to a test environment and a
production environment with the same Lago account.
## 1. Define a billable metric[](#1-define-a-billable-metric "Direct link to heading")
To define a billable metric through the user interface:
1. In the side menu, select **"Billable metrics"**;
2. Click **"Add a billable metric"** in the upper right corner;
3. Fill in the form ([learn more about billable metrics](/guide/billable-metrics/create-billable-metrics)); and
4. Click **"Add billable metric"** to save.
## 2. Create a plan (with charges)[](#2-create-a-plan-with-charges "Direct link to heading")
To create a plan through the user interface:
1. In the side menu, select **"Plans"**;
2. Click **"Add a plan"** in the upper right corner;
3. Fill in the form ([learn more about plans](/guide/plans/overview)); and
4. Click **"Add plan"** to save.
## 3. Create a customer[](#3-create-a-customer "Direct link to heading")
To create a customer through the user interface:
1. In the side menu, select **"Customers"**;
2. Click **"Add a customer"** in the upper right corner;
3. Fill in the form in the pop-up window
([learn more about customers](/guide/customers/customer-management)); and
4. Click **"Add customer"** to save.
You can also create customers through the API, as described in the
[documentation](/api-reference/customers/create).
## 4. Start a subscription[](#4-start-a-subscription "Direct link to heading")
To start a subscription, you need to assign a plan to an existing customer. To
do so through the user interface:
1. In the side menu, select **"Customers"**;
2. Select a customer from the list;
3. On the right-hand side, click **"Add a plan"**;
4. Select the plan you would like to assign to your customer; and
5. Click **"Add plan"** to confirm.
A success toast will be displayed and the new subscription will appear in the
customer view.
You can also start a subscription through the API, as described in the
[documentation](/api-reference/subscriptions/assign-plan).
## 5. Send usage-based events[](#5-send-usage-based-events "Direct link to heading")
Events sent from your backend to Lago will be automatically aggregated according
to the predefined billable metrics. To start sending usage-based events, please
refer to the [documentation](/guide/events/ingesting-usage).
## 6. Invoice your customers[](#6-invoice-your-customers "Direct link to heading")
At the end of the billing period, Lago will automatically generate an invoice
for each customer. Invoices will be sent to your application using webhooks. To
define the URL to which the webhooks will be sent:
1. In the side menu of the user interface, select **"Developers"**;
2. On the right-hand side, click **"Add a webhook"**;
3. Enter the URL of your application; and
4. Click **"Add webhook"** to confirm.
To learn more about webhooks and invoices, please refer to the
[API documentation](/api-reference/invoices/invoice-object).
# Welcome to Lago
Lago is an open-source software for metering and usage-based billing. It's the best alternative to Chargebee, Recurly or Stripe Billing for companies that need to handle complex billing logic.
This library will allow you to build an entire billing system from scratch. Lago is a real-time, event-based solution made for usage-based billing, subscription-based billing, and all the nuances of pricing in between.
You can use the [self-hosted version](/guide/self-hosted/docker) to deploy Lago on your existing
infrastructure or
[request access to Lago Cloud](https://forms.gle/eT7zgqcvq8dgt94g7) to start
using our solution immediately.
## Five-step billing workflow[](#five-step-billing-workflow "Direct link to heading")
### 1. Usage ingestion[](#1-event-ingestion "Direct link to heading")
[Events](/guide/events/ingesting-usage) provide information about your customers'
consumption, with the highest level of granularity. Any product feature for
which you want to charge your customers should correspond to a specific event.
An event can be triggered by an action or can be sent periodically. Lago is able
to ingest events at scale while preventing duplicates.
### 2. Metrics aggregation[](#2-metrics-aggregation "Direct link to heading")
The aggregation process consists in converting events into
[billable metrics](/guide/billable-metrics/create-billable-metrics). There are 4 aggregation types:
| Aggregation | Description | Type |
| -------------- | ------------------------------------------------------------------------------------------------------ | -------------------- |
| `COUNT` | Counts the number of times an incoming event occurs | Metered |
| `COUNT_UNIQUE` | Returns the number of unique values of a predefined property for incoming events | Metered or Recurring |
| `LATEST` | Returns the lastest value of a predefined property for incoming events | Metered |
| `MAX` | Returns the maximum value of a predefined property for incoming events | Metered |
| `SUM` | Calculates the sum of a predefined property for incoming events | Metered or Recurring |
| `WEIGHTED SUM` | Calculates the sum of a predefined property for incoming events prorated based on time used per period | Metered or Recurring |
### 3. Pricing and packaging[](#3-pricing "Direct link to heading")
Creating [plans](/guide/plans/overview) allows you to define how much your customers
should pay for using your product. You can then combine plans and billable
metrics to implement any billing model (i.e. subscription-based, usage-based, or
hybrid). Billable metrics may be priced differently depending on the associated
plan.
### 4. Invoicing[](#4-invoicing "Direct link to heading")
Lago automatically generates [invoices](/guide/invoicing/overview) for each customer
according to the plan model: the subscription fee can be billed at the beginning
or at the end of the billing period while usage-based charges are always
calculated at the end of the billing period. Invoices include fees, taxes and
customer information.
### 5. Payments[](#5-payments "Direct link to heading")
When an invoice is emitted and finalized, it's ready for payment collection.
Connect payment providers through [native integrations](/guide/payments/overview) or
trigger payments on any PSPs using the invoice payload created by Lago.
# Why billing is a nightmare
The original version of this article is available on [our
blog](https://www.getlago.com/blog/why-billing-systems-are-a-nightmare-for-engineers).
> *"On my first day, I was told: 'Payment will come later, shouldn't be hard
> right?'*
>
> *I was worried. We were not selling and delivering goods, but SSDs and CPU
> cores, petabytes and milliseconds, space and time. Instantly, via API.
> Fungible, at the smallest unit. On all continents. That was the vision.*
>
> *After a week, I felt like I was the only one really concerned about the long
> road ahead. In ambitious enterprise projects, complexity compounds quickly:
> multi-tenancy, multi-users, multi-roles, multi-currency, multi-tax codes,
> multi-everything. These systems were no fun, some were ancient, and often
> 'spaghetti-like'.*
>
> *What should have been a one-year R\&D project ended up taking seven years of
> my professional life, in which I grew the billing team from 0 to 12 people. So
> yes, if you ask me, billing is hard. Harder than you think. It's time to solve
> that once and for all."*
>
> Kevin Deldycke, former VP Engineering at Scaleway
This is a typical conversation we have with engineers on a daily basis.
After my last post about my
['pricing hack'](https://www.getlago.com/blog/pricing-my-only-growth-hack-at-qonto),
some of you asked me why billing was that complex. My co-founder Raffi took up
the challenge of explaining why it's still an unsolved problem for engineers.
We also gathered insights from other friends who went through the same painful
journey, including Algolia, Segment, Pleo... don't miss them! Passing the mic to
Raffi.
When you're thinking about automating billing, this means your company is
getting traction. That's good news!
You might then wonder: should we build it in-house? It does not look complex,
and the logic seems specific to your business. Also, you might want to preserve
your precious margins and therefore avoid existing billing solutions like Stripe
Billing or Chargebee, that take a cut of your revenue. Honestly, who likes this
'rent-seeker' approach?
Our team at Lago still has some painful memories of Qonto's internal billing
system, that we had to build and maintain. Why was it so painful? In this
article, I will provide a high-level view of the technical challenges we faced
while implementing hybrid pricing (based on subscription and usage) and what we
learned during this journey.
![How engineers feel about building a billing system](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/images/billing-nightmare-3c8b70de58b169f0a4f882549c9edcb7.png)
## TL;DR: Billing is just 100x harder than you will ever think[](#tldr-billing-is-just-100x-harder-than-you-will-ever-think "Direct link to heading")
"Let's bill yearly as well, should be pretty straightforward" claims the Revenue
team. Great! Everyone is excited to start working on it. Everyone, except the
Tech team. When you start building your internal billing system, it's hard to
think of all the complexity that will pop up down the road, unless you've
experienced it before.
It's common to start a business with a simple pricing. You define one or two
price plans and limit this pricing to a defined number of features. However,
when the company is growing, your pricing gets more and more complex, just like
your entire codebase.
At Qonto, our first users could only onboard on a €9 plan. We quickly decided to
add plans, and 'pay-as-you-go' features (e.g. ATM withdrawals, foreign currency
payments, capital deposit, etc.) to grow revenue.
Also, as Qonto is a neobank, we wanted to charge our customers' wallets
directly, through a ledger connected to our internal billing system. The team
started from a duo of full-time engineers building a billing system (which is
already a considerable investment) to a dedicated cross-functional Pricing team.
This is not specific to Qonto of course. Pleo, another fintech unicorn from
Denmark faced similar issues:
> *"I've learned to appreciate that billing systems are hard to build, hard to
> design, and hard to get working for you if you deviate from 'the standard'
> even by a tiny bit."*
>
> Arnon Shimoni, Product Billing Infrastructure Lead at Pleo
This is not even specific to fintechs. The Algolia team ended up creating a
whole pricing department, now led by Djay, a pricing and monetization veteran
from Twilio, VMWare, Service Now. They switched to a 'pay-as-you-go' pricing
model based on the number of monthly API searches.
> *"It looks easy on paper — however, it's a challenge to bring automation and
> transparency to a customer, so they can easily understand. There is a lot of
> behind-the-scenes work that goes into this, and it takes a lot of engineering
> and investment to do it the right way."*
>
> Bernardette Nixon, CEO at Venture Beat
## Dates[](#dates "Direct link to heading")
When implementing a billing system, dealing with dates is often the number 1
complexity. Somehow, all your subscriptions and charges are based on a number of
days. Whether you make your customers pay weekly, monthly or yearly, you need to
define the billing period.
Here is a non-exhaustive list of difficulties for engineers:
1. How to deal with leap years?
2. Do your subscriptions start at the beginning of the month or at the creation
date of the customer?
3. How many days/months of trial do you offer?
4. Who decided February only holds 28 days?
5. Wait, point 1 is also important for February...
6. How to calculate usage-based charges (price per second, hour, day)?
7. Do I resume the consumption or do I stack it month over month? Year over
year?
8. Do I apply a pro-rata based on the number of days consumed by my customer?
Although every decision is reversible, billing cycle questions are often the
most important source of customer support tickets, and iterating on them is
quite complex. For instance, Qonto switched from 'anniversary' dates to calendar
dates for its billing periods (see
[here](https://medium.com/qonto-way/biller-migration-how-we-changed-our-billing-cycle-cf3c4cdd7cf4)).
This change was not trivial.
## Upgrades & Downgrades[](#upgrades--downgrades "Direct link to heading")
You need to allow your customers to upgrade or downgrade their subscriptions.
Moving from plan A to plan B seems pretty easy, but it's not. Let's zoom on
potential edge cases.
What should we do when the user:
1. Upgrades or downgrades in the middle of a period;
2. Has paid for the original plan in advance;
3. Needs to pay for the original plan in arrears;
4. Downgrades from a yearly plan to a monthly plan;
5. Upgrades from a monthly plan to a yearly plan;
6. Upgrades or downgrades from a plan paid in advance to a plan paid in arrears
(and vice-versa); or
7. Has a discount and upgrades/downgrades?
We did not have a free trial period at the time at Qonto, but Arnon from Pleo
describes this situation
[here](https://arnon.dk/5-things-i-learned-developing-billing-system/).
## Usage-based computations[](#usage-based-computations "Direct link to heading")
Subscription-based billing is the first step when implementing a billing system.
Each customer needs to be affiliated to a plan in order to start charging the
right amount at the right time.
But for a growing number of companies, like Qonto, other charges come alongside
this subscription. These charges are based on what customers really consume.
This is what we call 'usage-based billing'. Most companies end up having a
hybrid pricing model: a monthly subscription fee and 'add-ons' or
'pay-as-you-go' charges on top of it.
These consumption-based charges are tough to track at scale, because they often
come with calculation rules performed on a high volume of events.
Here are some examples:
Segment's pricing is based on the number of monthly tracked users. This means
that they need to count the distinct number of users each month and reset this
value to zero for the next billing period. In order to retrieve the number of
unique visitors, they need to apply a 'distinct' function to deduplicate them.
![Event related to tracked users](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/tracked-users-event-f81fc6d343efffad1c4b3355517d90db.png)
![Event aggregation for tracked users](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/tracked-users-aggregation-1c662afae3af55c1d1b43793d0f56cc8.png)
Algolia tracks the number of API searches per month. This means they need to sum
the number of monthly searches for each customer and reset this value to zero
for the next billing period.
![Event related to API searches](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/api-search-event-9e90f7f9c063238a4e14cfd03d314a1e.png)
![Event aggregation for API searches](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/api-search-aggregation-23924f13dd3da2e5d73388afffe7e89a.png)
It becomes even more complex when you start calculating charges based on a
timeframe. For instance, Snowflake charges for the compute usage of a data
warehouse per second. This means that they sum the number of gigabytes or
terabytes consumed, multiplied by the number of seconds of compute time.
Consider the example of a utility company that charges \$10 per kilowatt of
electricity per hour. The illustration below shows what needs to be modeled and
automated by the billing system.
![Power consumption diagram](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/power-consumption-aba79c1bc4259e79144011519a519586.png)
* **Hour 1**: 10 KW used for 0.5 hour = 5 KW (10 x 0.5)
* **Hour 2**: 20 KW used for 1 hour = 20 KW (20 x 1)
* **Hour 3**: 0 KW used for 1 hour = 0 KW (0 x 1)
* **Hour 4**: 30 KW used for 0.5 hour = 15 KW (30 x 0.5)
* **TOTAL** = 40 KW used x $10 ⇒ $40
## Idempotency done right[](#idempotency-done-right "Direct link to heading")
Billing errors sometimes occur. Charging a user twice for the same product is
obviously bad for the customer experience, but failing to charge when needed
hurts revenue. That's partly why Finance and BI teams spend so much time on
revenue recognition.
For 'pay-as-you-go' companies, the billing system will process a high volume of
events. When an event needs to be replayed, it needs to happen without billing
the user again. Engineers call it 'idempotency', which means the **ability to
apply the same operation multiple times without changing the result beyond the
first try**.
It's a simple design principle, however, maintaining it at all times is hard.
## The case for a Cash Collection Officer[](#the-case-for-a-cash-collection-officer "Direct link to heading")
Cash collection is the process of collecting the money that customers owe you.
The pet peeve of cash collection is dunning: when payments fail, the merchant
needs to persist and make repeated payment requests to their customers, while
trying not to damage the relationship.
At Qonto, we called these 'waiting funds'. A client's status was 'waiting funds'
when they successfully went through the sign-up, KYC and KYB process but their
account balance was still 0.
For a neobank, the impact is twofold: you can't charge your service fees (e.g.
monthly subscription) and your customer does not generate interchange revenues
(e.g. when you make a payment of $100 with your card, the card issuer earns
$0.5-\$1 of interchange revenue through the merchant's fees).
Therefore, your two main revenue streams are 'null' but you did pay to acquire,
onboard, KYC the user and then to produce and send them a card. We often
half-joked about the need to hire a 'chief waiting funds officer': the financial
impact of this is just as high as the problem is underestimated.
All companies face dunning challenges. For engineers, on top of the billing
architecture, this means that they need to design and build:
1. A **'retry logic'** to ask for a new payment intent;
2. An **invoice reconciliation system** (e.g. if several months of charges are
recovered);
3. An **app logic to disable access** to the service; and
4. An **emailing workflow** to urge a user to proceed to the payment.
Some SaaS are even on a mission to fight dunnings and have built full-fledged
companies around cash collection, such as Upflow, which is used by successful
B2B scale-ups, including Front and Lattice.
> *"Sending quality and personalized reminders took us a lot of time and, as
> Lattice was growing fast, it was essential for us to scale our cash collection
> processes. We use Upflow to personalize how we ask our customers for money,
> repeatedly, while keeping a good relationship. We now collect 99% of our
> invoices, effortlessly."*
>
> Jason Lopez, Controller at Lattice
## The labyrinth of taxes and VAT[](#the-labyrinth-of-taxes-and-vat "Direct link to heading")
Taxes are challenging and depend on multiple dimensions. Taxes depend on what
you are selling, your home country and your customer's home country. In the
simplest situations, your tax decision tree should look like this:
![Decision tree for taxes](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/introduction/images/taxes-vat-46fc3b96167c21bc33b279431aa187ca.png)
Now, imagine that you sell different types of goods/services to different types
of customers in 100+ countries. If you think the logic on paper looks complex,
the engineering challenge is tenfold. Engineers need to think of an entire tax
logic within the application. This pyramidal logic is based on customers and
products, including:
1. **Taxes at company level**: your company will have a general tax rate that
applies to all customers by default;
2. **Taxes at customer level**: the default tax rate can be overridden for each
customer, depending on the dimensions mentioned above (see illustration); and
3. **Taxes at feature level**: this is mostly the case for the banking industry.
At Qonto for instance, banking fees are not subject to taxes but a 20% VAT
rate applies to non-banking features.
With billing, the devil's in the detail, which is why I always cringe when I see
engineering teams build a home-made system, just because they think "it's not
that complex".
If you've already tackled the topics listed above and think it's a good
investment of your engineering time, go ahead and build it in-house, but make
sure to budget for the maintenance work that is always needed. Another option is
to rely on existing billing platforms, built by specialized teams.
To solve this problem at scale, we've adopted a radical approach: we're building
an open-source billing API for product-led SaaS. Our API and architecture are
open, so that you can embed, fork and customize them as much as your pricing and
internal processes require.
If you're interested, you can [get started](https://www.getlago.com/get-started)
here or [book a demo](https://forms.gle/eT7zgqcvq8dgt94g7).
# Download invoices
When a new invoice is `finalized`, Lago will automatically send a
[webhook](/api-reference/webhooks/messages) to notify you. It will also generate a PDF
file that you can download and send to your customer.
To download an invoice through the user interface:
1. Click **"Customers"** in the side menu;
2. Select a customer from the list;
3. Open the **"Invoices"** tab;
4. Click the **ellipsis icon** on the right of the invoice; and
5. Click **"Download invoice"** to open the file in a new tab.
You can also download invoices via API ([learn more](/api-reference/invoices/download)).
```bash Download an invoice PDF
LAGO_URL="https://api.getlago.com"
INVOICE_ID="__YOU_INVOICE_ID__"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/invoices/$INVOICE_ID/download" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json'
```
## How to modify the invoice template[](#how-to-modify-the-invoice-template "Direct link to heading")
Changes to the invoice template and new information about your organization do not affect existing invoices and only apply to future invoices.
### Add information about your organization
You can modify some of the elements that are included in the PDF invoice, such as information about the organization, its logo and the footer.
To update your organization's information and logo:
1. Click **"Settings"** in the side menu;
2. In the **"Organization"** tab, click **"Edit"** in the **"Information"** block;
3. Choose a file to update the logo and fill out the form to update your organization's information; and
4. Click **"Save information"** to confirm.
For the logo, you can upload a JPG or PNG file with a maximum size of 800 KB.
### Add a custom footer
To update the footer of the invoice:
1. Click **"Settings"** in the side menu;
2. Open the **"Invoice"** tab;
3. Select **"Edit"** in the **"Invoice default footer"** block;
4. Enter your text (maximum 600 characters); and
5. Click **"Save information"** to confirm.
You can update the customer footer of invoices by changing the `invoice_footer` in the `billing_configuration` object of your organization endpoint.
```bash Update the customer footer of your invoices
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"name": "Name1",
"webhook_url": "https://test-example.example",
"country": "CZ",
"address_line1": "address1",
"address_line2": null,
"state": "state1",
"zipcode": "10000",
"email": "org@email.com",
"city": "city125",
"legal_name": null,
"legal_number": null,
"tax_identification_number": "EU123456789",
"timezone": "Europe/Paris",
"email_settings": [
"invoice.finalized",
"credit_note.created"
],
"billing_configuration": {
"invoice_footer": "footer custom",
"invoice_grace_period": 3,
"document_locale": "fr",
}
}
}'
```
### Translate invoices
To set the default language for documents:
1. Click **"Settings"** in the side menu;
2. Open the **"Invoice"** tab;
3. Select **"Edit"** in the **"Document language"** block;
4. Select your preferred language from the list; and
5. Click **"Edit language"** to confirm.
The organization's default language can be overwritten by the customer's preferred language ([learn more](/guide/customers/invoice-customer#preferred-language)).
You can update the customer footer of invoices by changing the `document_locale` in the `billing_configuration` object of your organization endpoint.
```bash Update the documents locale
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"name": "Name1",
"webhook_url": "https://test-example.example",
"country": "CZ",
"address_line1": "address1",
"address_line2": null,
"state": "state1",
"zipcode": "10000",
"email": "org@email.com",
"city": "city125",
"legal_name": null,
"legal_number": null,
"tax_identification_number": "EU123456789",
"timezone": "Europe/Paris",
"email_settings": [
"invoice.finalized",
"credit_note.created"
],
"billing_configuration": {
"invoice_footer": "footer custom",
"invoice_grace_period": 3,
"document_locale": "fr"
}
}
}'
```
Please refer to the API documentation to see the [list of supported languages](/api-reference/resources/locales).
# Export invoices
Lago enables you to filter invoices and export them as a simple or advanced CSV file, tailored to your needs.
## Invoice filtering options
With Lago, filtering your invoice list is straightforward and customizable. To filter invoices effectively, follow these steps:
1. Go to the **Invoices** section;
2. **Use quick filters** for fast, predefined filtering;
3. Select the **Filters options** for more advanced filtering criteria; and
4. Click **Reset filters** to remove all active filters when needed.
Here is the list of filter options you will encounter in Lago:
* **Currency:** Filter invoices based on the currency in which they are issued;
* **Customer:** Filter by the customer associated with the invoices;
* **Disputed:** Filter invoices to show only those that are disputed or undisputed;
* **Issuing Dates:** Filter invoices by their issuing dates;
* **Overdue:** Filter to display only overdue invoices;
* **Payment Status:** Filter invoices by their payment status;
* **Status:** Filter invoices by their status; and
* **Type:** Filter invoices by their type.
## Basic invoices export
The first option is a basic invoice export. This process generates a CSV file containing one row per invoice, based on the filters you have previously applied.
The exported CSV includes relevant invoice details and is sent to the email address of the user who requested the export.
The download link for the CSV file remains valid for 7 days.
## Detailed invoice fees export
The second option is an advanced invoice export. This process generates a CSV file containing one row per fee (line item of your invoices),
based on the filters you have previously applied. The exported CSV includes detailed information on each fee and line item of your invoices, and is
sent to the email address of the user who requested the export. The download link for the CSV file is valid for 7 days.
# Fees
A fee is a line item in an invoice.
There are few types of fees:
* **Subscription fees** that correspond to the base amount of the plan;
* **Charge fees** that correspond to usage-based charges (i.e. the costs
associated with each billable metric), this fee can be linked to a true-up fee;
* **Add-on fees** that correspond to a line item appearing in a one off invoice; and
* **Credit** that correspond to line item appearing in credit notes.
Information about fees includes (but is not limited to):
* Type;
* Amount;
* Currency; and
* Taxes.
The fee object is embedded within an invoice or credit note object, making it retrievable on its own.
This is illustrated below.:
```json
{
"fee": {
"lago_id": "e7e0ee24-7ef3-4b19-8bbf-fb0e75f5c79b",
"lago_group_id": null,
"lago_invoice_id": "ffbafe19-2b8d-4376-9510-314566b90724",
"lago_true_up_fee_id": null,
"lago_true_up_parent_fee_id": null,
"item": {
"type": "add_on",
"code": "test",
"name": "Test ",
"lago_item_id": "1e8d90cb-e305-438b-86b5-a566e97209d0",
"item_type": "AddOn"
},
"pay_in_advance": false,
"invoiceable": true,
"amount_cents": 10000,
"amount_currency": "USD",
"taxes_amount_cents": 3000,
"taxes_rate": 30.0,
"total_amount_cents": 13000,
"total_amount_currency": "USD",
"units": "1.0",
"description": "",
"unit_amount_cents": 10000,
"events_count": null,
"payment_status": "pending",
"created_at": "2023-07-06T21:01:41Z",
"succeeded_at": null,
"failed_at": null,
"refunded_at": null,
"vat_amount_cents": 3000,
"vat_amount_currency": "USD",
"applied_taxes": [
{
"lago_id": "3bdac336-af27-4be4-a4a5-58433f401708",
"lago_fee_id": "e7e0ee24-7ef3-4b19-8bbf-fb0e75f5c79b",
"lago_tax_id": "38325421-2145-4b79-bff1-d38a702afe3a",
"tax_name": "TVA",
"tax_code": "french_standard_vat",
"tax_rate": 20.0,
"tax_description": "French standard VAT",
"amount_cents": 2000,
"amount_currency": "USD",
"created_at": "2023-07-06T21:01:41Z"
}
]
}
}
```
## Update fee payment status
The `payment_status` of a fee can only be configured if `lago_invoice_id` is
`null`.
This option allows you to define the payment status of a fee yourself. The available options are: `pending`, `succeeded`, `failed`, and `refunded`.
Note that `payment_status` is used to group fees with a `succeeded` status into a specific invoice if `regroup_paid_fee` is set to `invoice`. Outside of this process, the `payment_status` is for your internal use.
## Delete a fee
The deletion of a fee can only be doable if `lago_invoice_id` is `null`.
This option allows you to delete a fee that is not linked to any invoice. Please refer to charge [invoiceable or not](/guide/plans/charges/invoiceable-vs-noninvoiceable) for more details.
# Grace period
**PREMIUM FEATURE** ✨
This feature is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
A grace period is defined as a number days during which invoices remain in
`draft` status, allowing you to review them and make changes before they are
`finalized` and sent for payment collection.
In the example below, the timeline includes a billing period of one month and a
grace period of three days.
## Define a grace period at organization level[](#define-a-grace-period-at-organization-level "Direct link to heading")
The organization's grace period applies to all customers by default.
To define a grace period at organization level through the user interface:
1. Access the **"Settings"** section via the side menu;
2. Open the **"Invoice"** tab;
3. Click **"Edit"** in the **"Grace period"** section;
4. Enter the number of days associated with the grace period; and
5. Click **"Edit grace period"** to confirm.
If you shorten the organization's grace period, some invoices in `draft`
status may be automatically `finalized`. For instance, if the initial grace
period was five days, but then three days into the grace period you decide to
reduce it to two days, then all `draft` invoices will automatically switch to
`finalized`.
You can also modify the organization's grace period at any time through [the API](/api-reference/organizations/update).
Define a grace period in days by using the `invoice_grace_period` argument in the `billing_configuration` object at an organization level.
```bash Add a grace period on the organization {28}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"name": "Name1",
"webhook_url": "https://test-example.example",
"country": "CZ",
"address_line1": "address1",
"address_line2": null,
"state": "state1",
"zipcode": "10000",
"email": "org@email.com",
"city": "city125",
"legal_name": null,
"legal_number": null,
"tax_identification_number": "EU123456789",
"timezone": "Europe/Paris",
"email_settings": [
"invoice.finalized",
"credit_note.created"
],
"billing_configuration": {
"invoice_footer": "footer custom",
"invoice_grace_period": 3,
"document_locale": "fr",
"vat_rate": 15.0
}
}
}'
```
## Define a grace period at customer level[](#define-a-grace-period-at-customer-level "Direct link to heading")
To define a grace period at customer level through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. Open the **"Settings"** tab of the customer view;
4. Click **"Add grace period"** in the **"Grace period"** section;
5. Enter the number of days associated with the grace period; and
6. Click **"Add grace period"** to confirm.
If you shorten the customer's grace period, some invoices in `draft` status
may be automatically `finalized`. For instance, if the initial grace period
was five days, but then three days into the grace period you decide to reduce
it to two days, then all `draft` invoices will automatically switch to
`finalized`.
You can also modify the customer's grace period at any time through the user interface or [the API](/api-reference/customers/create).
Define a grace period in days by using the `invoice_grace_period` argument in the `billing_configuration` object at a customer level.
```bash Add a grace period on the customer {28}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"address_line2": "",
"city": "Woodland Hills",
"country": "US",
"currency": "EUR",
"email": "dinesh@piedpiper.test",
"legal_name": "Coleman-Blair",
"legal_number": "49-008-2965",
"tax_identification_number": "EU123456789",
"logo_url": "http://hooli.com/logo.png",
"name": "Gavin Belson",
"phone": "1-171-883-3711 x245",
"state": "CA",
"timezone": "Europe/Paris",
"url": "http://hooli.com",
"zipcode": "91364",
"tax_codes": []
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"document_locale": "fr",
},
"metadata": [
{
"key": "Name",
"value": "John",
"display_in_invoice": true
}
]
}
}'
```
The customer's grace period overrides the organization's grace period. It only
applies to the customer with whom it is associated.
## Application scope and possible actions[](#application-scope-and-possible-actions "Direct link to heading")
The grace period applies to **subscription invoices**. It does not apply to
invoices related to add-ons or credit purchases.
The creation of a `draft` invoice triggers the `invoice.drafted`
[webhook](/api-reference/webhooks/messages).
When a subscription invoice is in `draft` status, you can:
* **Add usage records** by sending events with a `timestamp` within the relevant
billing period;
* **Edit a specific fee** by adjusting the total amount or the total units;
* **Apply coupons** to the customer's account; and
* **Add credits** to the customer's wallet and credit note wallet.
### Edit a specific fee
To edit a specific fee, follow these steps in the Dashboard:
1. Open a draft invoice's details page;
2. Click the 'three dots' icon next to the desired fee;
3. Change the invoice's display name if needed; and/or
4. Select either `Total amount` or `Total unit` for adjustment;
5. For `Total amount`, enter units and unit amount. Note: This will overwrite existing fee details.
6. For `Total unit`, input new units. Lago will then automatically recalculate the fee based on the charge model.
This action is exclusive to the Dashboard.
### Add usage records
In order to add usage to an invoice that is in `draft` status, the `timestamp`
of the [events](/guide/events/ingesting-usage) must be
within the billing period. Consider the following example:
> The billing period started on January 1st and ended on January 31st. We have
> defined a 3-day grace period and today is February 2nd.
>
> On February 1st, Lago automatically generated a `draft` invoice for the period
> January 1st to January 31st.
>
> We want to send additional usage records for this invoice. To do so, the
> timestamp of our events must be included in the period January 1st to January
> 31st.
>
> `1673457300` (i.e. January 11th, 2023) is a valid timestamp, therefore the
> event will be included in the `draft` invoice.
>
> However, `1675354500` (i.e. February 2nd, 2023) is outside the billing period
> under consideration, therefore the event will not be included in the `draft`
> invoice, it will be included in the next invoice.
After sending events, you can **go to the invoice list and refresh** the
corresponding `draft` invoice to ensure your new events have been taken into
account.
When all changes have been made, you can either wait for the grace period to
expire (the invoice status will automatically switch to `finalized`) or you can
**finalize the invoice manually** through the user interface or the API.
When an invoice is `finalized`, it can no longer be edited. Finalizing an
invoice triggers the `invoice.created` webhook.
Coupons and credits that are applied/added during the grace period will not
appear on `draft` invoices but will be automatically deducted from the
customer's next `finalized` invoice.
# Invoice metadata
## Add metadata on invoice
Adding metadata to an `invoice` object can provide additional structured information and context. For example, after finalizing the invoice, you can define a key-value pair in the `invoice` object to store your local invoice ID from your government invoicing system. To do so:
1. Navigate to the Invoice detail page to target a specific invoice;
2. Click on "Add metadata";
3. Add the information (kindly note, a key cannot exist without its corresponding value, and vice versa); and
4. Save to confirm.
The invoice metadata will be included in the `invoice` object but will not be displayed on the PDF file.
## Edit metadata on invoice
**To edit metadata from the user interface:**
1. Navigate to the Invoice detail page to target a specific invoice;
2. Click on "Edit metadata";
3. Add, edit, remove information (kindly note, a key cannot exist without its corresponding value, and vice versa); and
4. Save to confirm.
**To edit metadata using the API:**
1. In your payload, locate the key-value pair with the metadata ID you want to edit; and
2. Modify the key and/or value as needed.
When editing invoice metadata through the API, please make sure to include the existing metadata in your payload to avoid removing it.
## Delete metadata on invoice
**To delete a metadata key-value pair from the user interface:**
1. Navigate to the Invoice detail page for the specific invoice;
2. Click on "Edit metadata";
3. Click on the trash icon next to the metadata you want to remove; and
4. Save to confirm.
**To delete a metadata key-value pair from the API:**
1. Do not include the metadata ID you want to delete in your payload.
## Invoice metadata limitations
1. You can add up to 5 metadata key-value pairs;
2. Keys must be strings of 20 characters maximum; and
3. Values must be strings of 255 characters maximum.
# Net payment term
A net payment term refers to the specified number of days within which the end customer is required to settle the invoice after its finalization.
This term not only affects the `payment_due_date` within the invoice payload but also influences the due date mentioned in the downloadable PDF version of the invoice.
To illustrate, consider the following scenario:
a billing cycle spanning one month, accompanied by a net payment term of 15 days.
## Application scope[](#application-scope "Direct link to heading")
The net payment term period applies to all types of invoices.
It does not trigger any webhook when the `payment_due_date` becomes overdue.
The net payment term period applies to all types of invoices and is used to compute the due date. When the `payment_due_date` has passsed, the invoice is flagged as `Overdue`. This action sets the `payment_overdue` field to true, until the payment is `succeeded`, `payment_dispute_lost_at` is applied, or the invoice is voided.
## Define a net payment term at organization level[](#define-a-net-payment-term-at-organization-level "Direct link to heading")
The organization's net payment term applies to all customers by default.
To define a net payment term at the organization level via the user interface, follow these steps:
1. Access the **"Settings"** section using the side menu;
2. Navigate to the **"Invoice"** tab;
3. Click **"Edit"** in the **"Net payment term"** section;
4. Select the desired number of days for the payment term or opt for a custom duration; and
5. Confirm by clicking **"Edit net payment term"**.
You can also modify the organization’s net payment term at any time through [the API](/api-reference/organizations/update).
Define a net payment term in days by using the `net_payment_term` argument within the `organization` object.
```bash Add a net payment term on the organization
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"net_payment_term": 15
}
}'
```
## Define a net payment term at customer level[](#define-a-net-payment-term-at-customer-level "Direct link to heading")
To define a net payment term at the customer level through the user interface, follow these steps:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. Open the **"Settings"** tab of the customer view;
4. Click **"Add a net payment term"** in the **"Net payment term"** section;
5. Choose the desired number of days for the payment term or opt for a custom duration; and
6. Click **"Add net payment term"** to confirm.
You can also modify the customer's net payment term at any time through [the API](/api-reference/customers/update).
Define a net payment term in days by using the `net_payment_term argument` within the `customer` object.
```bash Add a net payment term on a customer
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"net_payment_term": 15
}
}'
```
The customer's net payment term supersedes the one defined at the organization level.
It exclusively applies to the associated customer.
# Overview
Lago automatically generates invoices for each customer according to the plan model.
When a new invoice is generated, Lago also sends an `invoice.created` webhook
([learn more](/api-reference/webhooks/messages)).
When an invoice is linked to an add-on, another type of webhook is sent, called
`invoice.add_on_added`.
## Invoice object[](#invoice-object "Direct link to heading")
Invoices include (but are not limited to):
* Invoice number;
* Billing period;
* Customer information;
* Fees; and
* Taxes.
You can [download invoices](/guide/invoicing/download-invoices) or use the
[invoice object](/api-reference/invoices/invoice-object) to create your own invoice
template.
You can also use the invoice object to transmit information to your accounting
software or payment service provider.
## Invoice numbering[](#invoice-numbering "Direct link to heading")
With Lago, invoice numbering is generated every time an invoice is finalized. You have the flexibility to customize how invoice numbers are incremented to align with your organizational structure and customer management approach.
* **Invoice numbering per customer**: This setting is designed to increment invoice numbers individually for each customer.
It ensures that each customer has their own unique sequence of invoice numbers, separate from other customers.
This approach is ideal for maintaining distinct and isolated numbering patterns for each customer, aiding in clear tracking and accounting processes.
* **Invoice numbering across the organization**: Opting for this method applies a global sequence for incrementing invoice numbers across your entire organization. Instead of having individual sequences for each customer, all invoices within the organization follow a single, unified numbering system. This creates a continuous and organization-wide sequence for all invoice numbers, simplifying the invoice management process. In that case, invoices are incremented per month (dynamic value used is `YYYYMM`).
## Invoice prefix customization[](#invoice-prefix-customization "Direct link to heading")
Lago also allows you to customize the prefix for documents, including invoices and credit notes.
By default, Lago auto-generates this prefix by combining the first three letters of your organization's name with the last four digits of your organization ID. However, you have the flexibility to fully customize this field to better align with your organization's branding or numbering conventions. This feature ensures clarity and consistency across your documents while allowing you to maintain a professional and personalized appearance in your invoicing system.
## Custom invoice grouping[](#invoice-grouping "Direct link to heading")
Grouping invoice line items in a way that provides clearer insight for your customers can be more beneficial than sticking to the default charge setup in Lago.
For instance, as an AI service provider, you might prefer to regroup all fees associated to one charge by a specific `model` used by a customer, without the need to individually list each model in Lago.
When setting up a charge with a `standard` charge model, you can use `model_name` as an event property in the `grouped_by` attribute. If every event reported to Lago includes a `model_name`, Lago is capable of adjusting your invoice so that charges are organized under the respective model name for that particular charge. Consequently, Lago will also automatically allocate the usage costs for each model.
You can specify multiple `grouped_by` keys for your charge; the order you set them in dictates how they will be displayed on the invoice, affecting the presentation of charges.
The `grouped_by` feature is exclusively available for the `standard` charge model.
## Finalize empty invoices
By default, Lago finalizes all invoices, including those with a final amount of zero. However, some customers may prefer to skip empty invoices to avoid unnecessary accounting documents.
In such cases, you **can configure Lago to skip the issuance of invoices when they are empty**.
### Empty invoices definition
Lago considers an invoice empty only if it has no line items before applying coupons or discounts.
If an applicable discount reduces an invoice's total to zero, Lago will not consider this invoice as part of the empty invoices scope and will still finalize it.
### Organization level
The `finalize_zero_amount_invoice` setting is set to `true` by default. At the organization level, you can change this value to `false` at any time.
When set to `false`, empty invoices won't be finalized for any customers unless specifically overridden at the customer level.
To modify this setting from the Lago user interface:
1. Go to Settings in your app;
2. Navigate to the Invoices section; and
3. Update the value in the **'Finalize zero amount invoice'** section according to your preference.
```bash Update the organization's settings
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/organizations" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"organization": {
"country": "US",
"finalize_zero_amount_invoice": true
}
}'
```
### Customer level
By default, new customers inherit the `finalize_zero_amount_invoice` setting from the organization.
You can override this setting for individual customers to meet specific needs.
The available options are:
* `inherit`: Follows the organization's setting;
* `skip`: Skips finalizing empty invoices; or
* `finalize`: Always finalizes invoices, even if empty.
To modify this customer setting from the Lago user interface:
1. Go to a specific customer;
2. Navigate to the Settings section; and
3. Override the value in the **'Finalize zero amount invoice'** section according to your preference.
```bash Update the customer's settings
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "hooli_12345",
"address_line1": "100 Fintech Devcon Street",
"city": "Austin",
"country": "US",
"email": "hooli@fintech.com",
"legal_number": "54321",
"name": "Hooli 12345",
"state": "Texas",
"tax_identification_number": "1234",
"zipcode": "9399",
"finalize_zero_amount_invoice": "skip"
}
}'
```
# Taxes
When generating invoices, you may need to apply vat or other taxes. By creating taxes and applying them to the organization or/and customers, their invoices will be directly affected.
## Create taxes[](#create-taxes "Direct link to heading")
**Follow those steps to add a new tax:**
1. Access the tax settings page through the **Settings** section > **Taxes** tab;
2. In the upper right corner of the list, click **"Add"** to create a new tax;
3. Enter its `name`;
4. Assign it a unique `code` (i.e. unique ID as defined in your backend system);
5. Add a `description` *(optional)*; and
6. Define the `rate` that applies.
```bash Premium Plan Example
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/taxes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"tax": {
"name": "french vat",
"code": "french_vat",
"description":"French standard VAT",
"rate": 20.00,
"applied_to_organization": false
}
}'
```
## Editing and deleting taxes[](#edit-delete-taxes "Direct link to heading")
A tax can be deleted or edited even if it is linked to an organization or a customer.
However, it's important to note that any change made to a tax object, including its removal, has an impact on all existing draft invoices or upcoming invoices associated with this tax.
Available actions include:
* **Edit**: allows you to modify the name, code and rate of the tax object; and
* **Delete**: allows you to delete the tax object and remove it from the list (this action cannot be undone).
## Apply taxes to objects
When generating invoices, you may need to apply taxes.
The tax rate applies to all fees (i.e. subscription fees and charges) and appears on the invoices.
### Taxes at the organization level
To apply tax objects to the organization:
1. Access the invoice settings page through the **Settings** section > **Invoice** tab;
2. In the **Taxes on organization** section, click **"Add"** to add a new tax;
3. Select the tax object you want to apply; and
4. Repeat the action if you want to add another tax.
```bash Premium Plan Example
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/taxes" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"tax": {
"code": "french_vat",
"applied_to_organization": true
}
}'
```
### Taxes at the customer level
To apply tax objects to a specific customer:
1. Access the customer settings page through the **Customer** details page > **Settings** tab;
2. In the **Tax rates** section, click **"Add a tax"** to add a new tax;
3. Select the tax object you want to apply; and
4. Repeat the action if you want to add another tax.
```bash Premium Plan Example
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"code": "acme_inc",
"tax_codes": ["french_vat"]
}
}'
```
### Taxes at the plan and charges level
Follow these steps to apply tax objects to a plan:
1. Ensure that you have already created the necessary taxes on your account.
2. Navigate to the **Plan** section and click on **Add a plan**.
3. In the **Plan settings** section, click on **Add a tax rate**.
4. If you have usage-based charges, expand the **More options** section for the charge and click on **Add a tax rate** to define taxes specific to that charge.
5. **Note**: If taxes are defined on charges, they will override the tax rate defined at the plan level.
6. Complete the process of creating your plan and apply it to customers to generate an invoice.
```bash Add taxes to a plan and to charges
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Starter",
"code": "starter",
"interval": "monthly",
"description": "",
"amount_cents": 9900,
"amount_currency": "USD",
"trial_period": "",
"pay_in_advance": true,
"bill_charges_monthly": null,
"tax_codes": ["french_standard_vat"]
"charges": [
{
"lago_billable_metric_id": "61ddebee-f8ac-4794-90cf-d626b55ab0ed",
"billable_metric_code": "user_seat",
"charge_model": "standard",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"tax_codes":["french_standard_vat"]
"properties": {
"amount": "0.10"
}
}
]
}
}'
```
### Taxes at the add-on level
Follow these steps to apply tax objects to a add-on:
1. Make sure you have already set up the required taxes within your account.
2. Navigate to the "Add-ons" section and click on "Add an add-on."
3. Within the "Add-on settings" area, click on "Add a tax rate."
4. Finish creating your add-on and apply it to customers using a one-off invoice to generate the invoice.
```bash Add taxes to an add-on
{
"add_on": {
"name": "Setup fee",
"code": "setup_fee",
"amount_cents": 100000,
"amount_currency": "USD",
"description": "",
"tax_codes": ["french_standard_vat"]
}
}
```
Keep in mind that tax rates defined at the add-on level can be overridden when creating a one-off invoice.
## Tax hierarchy
### Invoice linked to a subscription
When an invoice linked to a subscription is generated,
the taxation process follows a hierarchy that determines how taxes are applied to different fees:
1. Taxes defined at the **organization** level will impact all invoice fees (subscription & charges).
2. Taxes defined at the **customer** level will override the organization-level taxes and impact all invoice fees (subscription & charges).
3. Taxes defined at the **plan** level will override the customer-level taxes and impact all invoice fees (subscription & charges).
4. Taxes defined at the **charge** level will override the plan-level taxes but will impact only the fee associated with that particular charge.
### Invoice linked to a one-off-invoice
When an invoice linked to a one-off is generated, the taxation process follows a hierarchy that determines how taxes are applied to different fees:
1. Taxes defined at the **organization** level will impact all invoice fees
2. Taxes defined at the **customer** level will override the organization-level taxes and impact all invoice fees
3. Taxes defined at the **add-on** level will override the customer-level taxes and impact only the fee associated with that particular add-on
4. While creating a one-off invoice, taxes defined at the **fees** level will override add-on-level taxes but will solely impact the fee associated with that particular add-on.
### Invoice linked to prepaid credit
Since we treat the purchase of credits as an upfront payment before usage, invoices generated for prepaid credit purchases will not include any taxes.
## Auto-detect european taxes with Lago
Lago now features an automatic European tax detection integration for your customers.
Check out our easy-to-follow [integration guide](/integrations/taxes/lago-eu-taxes).
# Void invoices
Voiding an invoice is akin to deleting or canceling it in principle.
Yet, voiding preserves a paper trail, enabling you to locate the invoice by its number.
Voided invoices are considered as having zero value for reporting and are not payable.
Importantly, this status is final, meaning the invoice's status remains unalterable.
Once you void an invoice, it remains accessible through the UI views and shows a status `voided` indicating it has been voided.
You can void an invoice only when it's in a `finalized` status, and the payment status is not `succeeded`.
To void an invoice using the user interface:
1. Go to the **"Invoices"** list;
2. Click the **ellipsis icon** on the right, on the line corresponding to the invoice;
3. Select **"Void invoice"**; and
4. Confirm to void the invoice.
```bash Void an existing invoice
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
INVOICE_ID="__YOUR_INVOICE_ID__"
curl --location --request POST "$LAGO_URL/api/v1/invoices/$INVOICE_ID/void" \
--header "Authorization: Bearer $API_KEY"
```
## Restrictions on voiding invoices
You cannot void an invoice when:
* The invoice is in `draft` status, as it hasn't been finalized yet; or
* The payment status of the invoice is `succeeded`, indicating that the payment has been successfully processed; or
* There is still credit available for one of the credit notes linked to the invoice; or
* The invoice has already been voided.
## Voiding invoices with applied discounts
* Coupons applied to an invoice marked as void are lost;
* Prepaid credits deducted from an invoice marked as void are refunded, provided the wallet is still active; and
* Credit notes applied to an invoice marked as void are refunded to the credit note wallet.
# Lago Cloud
Lago Cloud is the fully hosted version of our open-source billing API.
With a cloud account:
1. You don't have to maintain the solution;
2. You can start building your billing system immediately; and
3. You benefit from automatic updates.
[Request access to Lago Cloud](https://forms.gle/eT7zgqcvq8dgt94g7) to get
started.
# Lago OpenAPI
Using our Open API is a great way to explore and interact with Lago's API documentation.
## Prerequisites[](#prerequisites "Direct link to heading")
Before you start using our Open API, here are some important prerequisites and useful links:
1. Create a free [Postman](https://postman.com) account;
2. Use the [Swagger](https://swagger.getlago.com/) for Lago's API documentation;
3. Open a Lago account to get your API key; and
4. Check out our public [GitHub repository](https://github.com/getlago/lago-openapi).
## Using Lago Open API with Postman[](#using-lago-open-api-with-postman "Direct link to heading")
The Swagger used to document Lago's API can be imported directly into Postman. To do so:
1. **Copy the following link:** [https://swagger.getlago.com/openapi.yaml](https://swagger.getlago.com/openapi.yaml) (this link can also be found on the Swagger's page);
2. In Postman, under **Import > Link**, paste the URL above;
3. Click **Continue**;
4. Click the **Import** button; and
5. In the menu, under **API**, find the newly created **Lago API documentation**.
It only takes a few seconds to complete the import. You can then use this API to generate a new collection.
Please don't forget to enter the API key associated with your organization's Lago account to authenticate your API requests.
# Migration to v1.2.0
Dear Lago Community, 👋
We're writing to inform you of upcoming changes in the Lago API that may impact your workflows.
# Why are we doing this?
We understand that change can sometimes be challenging. However, we believe it's essential for growth and improvement.
In our continuous efforts to improve Lago's scalability and flexibility, we are updating our API to streamline the delivery of multiple features. This approach allows us to deliver more value to you and will pave the way for exciting new releases, including:
1. **Infinite Dimension Structure:** With filters, enjoy unlimited depth in dimension structures, enabling you to merge multiple billable metrics into a single event code;
2. **High Usage Ingestion System:** Overcome scalability issues with the ability to send over 10,000 events per second;
3. **Current/Past Usage Performance Improvements:** Experience near-real-time data query with enhanced performance for current and past usage endpoints;
4. **Alerting Scenarios:** Set up custom alerts for critical events such as unpaid invoices, reaching wallet credit thresholds, and many more;
5. **Workflow Creation:** Seamlessly trigger actions within Lago based on custom scenarios, like pausing subscriptions or upgrading plans based on alerts; and
6. **Entitlements Scenarios:** Utilize Lago's aggregated usage data to manage access to product features based on custom rules.
# Timeline
We will maintain the current API logic until **July 9, 2024**. However, after this date, previous versions will no longer be supported. We kindly ask you to update your integration before that day to avoid any potential breaking change.
# What are the changes?
## 1. Transition from `group` to `filters`
We're introducing a new method for building infinite levels of dimensions in Lago with the concept of `filters`.
Creating or editing billable metrics or plans via the user interface will result in the creation of `filters`.
Therefore, you may encounter issues if you make changes via the interface but still use `groups` when creating or editing objects via API.
### Impact on billable metrics
* Introducing `billable_metrics.filters`
* Deprecating `billable_metrics.group`
**Deprecating "billable\_metrics.group"**
The `group` object is deprecated and will be removed from the `billable_metric` object on July 9, 2024.
Please update all integrations currently using `billable_metrics.group` (see example below).
```diff "billable_metrics.group" with 1 level
{
"billable_metric": {
…
- "group": {
- "key": "provider",
- "values": ["AWS", "Google", "Azure"]
- }
+ "filters": [
+ {
+ "key": "provider",
+ "values": ["AWS", "Google", "Azure"]
+ }
+ ]
}
}
```
```diff "billable_metrics.group" with 2 levels
{
"billable_metric": {
…
- "group": {
- "key": "provider",
- "values": [
- {
- "name": "AWS",
- "key": "region",
- "values": ["Europe", "Africa", "Asia"]
- },
- {
- "name": "Google",
- "key": "region",
- "values": ["Europe", "North America"]
- },
- {
- "name": "Azure",
- "key": "region",
- "values": ["North America", "Asia"]
- }
- ]
- }
+ "filters": [
+ {
+ "key": "provider",
+ "values": ["AWS", "Google", "Azure"]
+ },
+ {
+ "key": "region",
+ "values": ["Europe", "Africa", "Asia", "North America"]
+ }
+ ]
}
}
```
Note that the billable\_metric object will only display filters and groups if
applicable.
### Impact on API endpoints
* Deprecating `List all billable metric groups`.
The endpoint `List all billable metric groups` is deprecated. It will be supported until July 9, 2024 and will then be removed.
```
GET https://api.getlago.com/api/v1/billable_metrics/{code}/groups
```
### Impact on plans
* Introducing `plans.charges.filters`
* Deprecating `plans.charges.group_properties`
**Deprecating "billable\_metrics.groups" with one level**
The `group_properties` object is deprecated and will be removed from `plans.charges` on July 9, 2024.
Please update all integrations currently using `plans.charges.group_properties` (see example below).
```diff
{
"plans": {
…
"charges": [
{
…
"properties": {
"amount": "0",
},
- "group_properties": [
- {
- "group_id": "__GROUP_ID__",
- "invoice_display_name": "AWS in Europe",
- "values": {
- "amount": "15",
- }
- },
- {
- "group_id": "__GROUP_ID__",
- "invoice_display_name": "Google in Europe",
- "values": {
- "amount": "20",
- }
- }
- ]
+ "filters": [
+ {
+ "values": {
+ "provider": "AWS",
+ "region": "Europe"
+ },
+ "invoice_display_name": "AWS in Europe"
+ "properties": { "amount": "15" }
+ },
+ {
+ "values": {
+ "provider": "Google",
+ "region": "Europe"
+ },
+ "invoice_display_name": "Google in Europe"
+ "properties": { "amount": "20" }
+ }
+ ]
}
}
}
```
Note that the plan object will only display filters and group\_properties if
applicable.
### Impact on fees
* Introducing `fees.lago_charge_filter_id`
* Deprecating `fees.lago_group_id`
**Deprecating "billable\_metrics.groups" with one level**
The `lago_group_id` field is deprecated and will be removed from `fees` on July 9, 2024.
Please update all integrations currently using `fees.lago_group_id` or `invoice.fees.lago_group_id` (see example below).
```diff
{
"fees": {
…
- "lago_group_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
+ "lago_group_id": null,
+ "lago_charge_filter_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
…
}
}
```
This change also affects the invoice object.
### Impact on customer usage
* Introducing `customer_usage.charges_usage.filters`
* Deprecating `customer_usage.charges_usage.groups`
**Deprecating "billable\_metrics.groups" with one level**
The `charges_usage.groups` field is deprecated and will be removed from `customer_usage` on July 9, 2024.
Please update all integrations currently using `customer_usage.charges_usage.groups` (see example below).
```diff
{
"customer_usage": {
…
"charges_usage": [
…
{
- "groups": [
- {
- "lago_id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
- "key": "null",
- "value": "europe",
- "units": "0.9",
- "amount_cents": 1000,
- "events_count": 10
- }
- ]
+ "filters": [
+ {
+ "values": {
+ "provider": "AWS",
+ "region": "Europe"
+ }
+ "units": "0.9",
+ "amount_cents": 1000,
+ "events_count": 10
+ }
+ ]
}
]
…
}
}
```
## 2. Mandatory `external_subscription_id` field in event payloads
To enable real-time functionalities, event payloads must include `external_subscription_id`.
Events that only include `external_customer_id` will not be taken into account when aggregating usage in upcoming versions.
* Making `events.external_subscription_id` required
**Making "events.external\_subscription\_id" required**
Sending `event.external_subscription_id` will be mandatory starting July 9, 2024.
Please update all integrations currently using `POST /events` (see example below).
```diff
{
"event": {
"transaction_id": "__UNIQUE_ID__",
- "external_customer_id": "__YOUR_CUSTOMER_ID__",
+ "external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"timestamp": $(date +%s),
"properties": {
"custom_field": 12
}
}
}
```
## 3. Deprecated fields
We will remove the following deprecated fields in order to preserve the quality of the API and for clarity.
| Deprecated field | Substitution field |
| ---------------------------------------------------- | ---------------------------------------------------- |
| `applied_coupon.expiration_date` | `applied_coupon.expiration_at` |
| `billable_metric.group` | `billable_metric.filters` |
| `coupon.expiration_date` | `coupon.expiration_at` |
| `credit.before_vat` | `credit.before_taxes` |
| `credit.item.lago_id` | `credit.item.lago_item_id` |
| `credit_note.balance_amount_currency` | `credit_note.currency` |
| `credit_note.credit_amount_currency` | `credit_note.currency` |
| `credit_note.refund_amount_currency` | `credit_note.currency` |
| `credit_note.sub_total_vat_excluded_amount_currency` | `credit_note.currency` |
| `credit_note.sub_total_vat_excluded_amount_cents` | `credit_note.sub_total_excluding_taxes_amount_cents` |
| `credit_note.total_amount_currency` | `credit_note.currency` |
| `credit_note.vat_amount_currency` | `credit_note.currency` |
| `credit_note.vat_amount_cents` | `credit_note.taxes_amount_cents` |
| `credit_note.vat_amount_currency` | `credit_note.currency` |
| `customer.billing_configuration.vat_rate` | `customer.taxes[].rate` |
| `customer_usage.amount_currency` | `customer_usage.currency` |
| `customer_usage.charge_usages.groups` | `customer_usage.charge_usages.filters` |
| `customer_usage.from_date` | `customer_usage.from_datetime` |
| `customer_usage.to_date` | `customer_usage.to_datetime` |
| `customer_usage.total_amount_currency` | `customer_usage.currency` |
| `customer_usage.vat_amount_cents` | `customer_usage.taxes_amount_cents` |
| `customer_usage.vat_amount_currency` | `customer_usage.currency` |
| `event_error.input_params.code` | `event_error.event.code` |
| `event_error.input_params.external_customer_id` | `event_error.event.external_customer_id` |
| `event_error.input_params.external_subscription_id` | `event_error.event.external_subscription_id` |
| `event_error.input_params.properties` | `event_error.event.properties` |
| `event_error.input_params.timestamp` | `event_error.event.timestamp` |
| `event_error.input_params.transaction_id` | `event_error.event.transaction_id` |
| `fee.unit_amount_cents` | `fee.precise_unit_amount` |
| `fee.vat_amount_cents` | `fee.taxes_amount_cents` |
| `fee.vat_amount_currency` | `fee.amount_currency` |
| `invoice.amount_currency` | `invoice.currency` |
| `invoice.amount_cents` | `invoice.fees_amount_cents` |
| `invoice.credit_amount_currency` | `invoice.currency` |
| `invoice.credit_amount_cents` | `invoice.credits[].amount_cents` |
| `invoice.fees.group_invoice_display_name` | `invoice.fees.filter_invoice_display_name` |
| `invoice.fees.lago_group_id` | n/a |
| `invoice.legacy` | n/a |
| `invoice.sub_total_vat_excluded_amount_cents` | `invoice.sub_total_excluding_taxes_amount_cent`s |
| `invoice.sub_total_vat_included_amount_cents` | `invoice.sub_total_including_taxes_amount_cent`s |
| `invoice.total_amount_currency` | `invoice.currency` |
| `invoice.vat_amount_cents` | `invoice.taxes_amount_cents` |
| `invoice.vat_amount_currency` | `invoice.currency` |
| `organization.billing_configuration.vat_rate` | `organization.taxes[].rate` |
| `plan.charges.group_properties` | `plan.charges.filters` |
| `subscription.subscription_date` | `subscription.subscription_at` |
| `wallet.balance` | `wallet.balance_cents` |
| `wallet.expiration_date` | `wallet.expiration_at` \` |
# Get involved
Your feedback is important to us. If you have any questions, encounter issues, or have suggestions, please reach out to us via the Slack community.
We understand that breaking changes may require you to adapt, so we apologize for any inconvenience caused. Our team is committed to providing support throughout this transition process to minimize disruptions.
Thanks for your understanding and continued support.
The Lago Team
# Create add-ons
Add-ons are a useful feature that allows you to add a fixed charge that is not recurring to one-off invoices. This can be used to apply one-time fees such as a setup fee, one-time payment, or customer success fee.
To create an add-on through the user interface, follow these steps:
1. Access the **"Add-ons"** section via the side menu;
2. Click **"Add an add-on"**;
3. Choose a name, a code, and a description (optional) for your add-on;
4. Define its default value and currency (these values can be overwritten when creating the invoice); and
5. Click **"Add add-on"** to confirm.
```bash Create an add-on for "Setup Fees"
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/add_ons" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"add_on": {
"name": "Setup Fee",
"code": "setup",
"amount_cents": 50000,
"amount_currency": "USD",
"description": "Charge a setup fee for new customers."
}
}'
```
In the add-ons section, you can edit or delete add-ons by clicking the ellipsis icon.
Editing allows you to modify the name, code, description, and settings of the add-on, while deleting removes the add-on
from the list (this action cannot be undone). Please note that you cannot edit or delete an add-on that has already been applied
to a customer.
To assign an add-on to a customer, you need to create a one-off invoice.
Simply select the add-on(s) you wish to apply from the add-ons section while creating the invoice, and the fixed charge
will be added to the total amount due.
# Issue one-off invoices
One-off invoices allow you to bill immediately one or several add-ons to a customer. This guide will show you how to create a one-off invoice for a specific customer using the add-ons.
## Create a one-off invoice
To create a one-off invoice for a specific customer:
1. Select the customer from the list of customers; and
2. Click the **"Actions"** button located in the upper-right corner and select **"Create one-off invoice"**.
## Adding add-ons to one-off invoices
Now that you have started the flow to create a one-off invoice, it's time to add one or several add-ons to it:
1. Click **"Add an add-on"** to add a new add-on to the invoice;
2. Edit the number of units applied for a specific add-on;
3. Edit the unit price of a specific add-on (you can define it as 0 if needed);
4. Edit the description of the add-on displayed on the invoice; and
5. Click **"Create"** to issue your one-off invoice.
```bash Assign add-ons to create a one-off invoice
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/invoices" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"invoice": {
"external_customer_id": "hooli_1234",
"currency": "USD",
"fees": [
{
"add_on_code": "setup_fee",
"units": 1,
"unit_amount_cents": 50000,
"description": "Implementation fee with a solution engineer"
},
{
"add_on_code": "customer_success",
"units": 2,
"unit_amount_cents": 100000,
"description": "One off customer success fee"
}
]
}
}'
```
## Application scope of one-off invoices
Here are a few things to keep in mind about one-off invoices:
* One-off invoices are issued immediately and can include the same add-on multiple times.
* If the currency of the customer is already defined, the currency of the one-off invoice must be the same.
* You can use the same add-on to create one-off invoices for multiple customers whose subscriptions don't have the same currency or to apply a different amount for one of these customers.
* Coupons or prepaid credits (discounts) **do not apply** to one-off invoices.
* One-off invoices are subject to taxes, as defined in the customer view.
Note that when using the API endpoint, if the amount and currency are null, Lago will apply the default amount and currency defined in the UI.
## Invoicing
As mentioned previously, a **one-off invoice is invoiced straight away**. You are able to find one-off invoices through webhook with webhook message called `invoice.one_off_created`.
# Adyen integration
Lago's native integration with Adyen allows you to collect payments automatically when new invoices are generated.
Lago's seamless integration with Adyen offers a wide range of payment options, enabling you to conveniently collect payments from your customers. Supported payment methods include:
* Card payments (Visa, MasterCard, CB)
* Apple Pay
* Paypal
* American Express
* Amazon Pay
* Google Pay
And many more! With Lago's native Adyen integration, you can offer your customers a variety of payment options, enhancing their convenience and flexibility during transactions.
## Connecting Lago to Adyen
To set up the Adyen integration in Lago from our user interface, follow these steps:
1. In the side menu of your Lago app, navigate to **Settings**;
2. Select the **Integrations** tab;
3. Click on **Adyen** and enter the required connection fields (described in the next section); and
4. Click **Connect to Adyen** to confirm the integration.
## Adyen Connection Fields
When connecting Lago to Adyen, you need to provide information for the following fields.
The API Key is a mandatory field and can be found in your Adyen account. Follow these steps to retrieve the API Key:
* Go to your Adyen account and navigate to **Developers** > **API Credentials**;
* On the API Credentials page, create new credentials with a type of **Web service user**;
* Click on the **Create credentials** button to generate the API Key; and
* Copy the API Key and paste it in the corresponding field in Lago. Remember to save the changes.
The Merchant Account is required to ensure that Lago targets the correct Adyen account. To find the Merchant Account:
* Go to **Settings** > **Merchant accounts** in your Adyen account; and
* Copy the **Account code** of the targeted account you want to use with Lago.
The Live Prefix represents the prefix url of your live Adyen account. This field is optional. If left empty, you can connect a test account. However, for live accounts, you must provide a Live Prefix. Follow these steps to obtain the Live Prefix:
* Go to **Developers** > **API URLs** > **Prefix** in your Adyen account.
Adyen's HMAC signatures are used to protect webhook endpoints and messages created by Adyen. Lago requires this signature to properly decrypt outgoing webhooks from Adyen. To find the HMAC Signature:
* Create or edit a webhook in Adyen by accessing **Developers** > **Webhooks**; and
* Under "Security" settings, you can find the HMAC Key.
The Live Prefix and HMAC Signature fields are optional and may not be required depending on your use case.
## Setting up Adyen's payments auto-capture
To enable automatic payment capture in your Adyen account, ensure that you have configured the account settings accordingly. Automatic payment capture allows for immediate processing without manual intervention. Refer to Adyen's documentation for instructions on [setting up auto capture](https://docs.adyen.com/online-payments/capture#automatic-capture).
## Turn on Adyen's recurring details
In Adyen, to enable recurring payments for a stored payment method, follow these steps:
1. Go to Developers > Additional Data;
2. Check the box for Recurring Details; and
3. Click Save.
## Setting up Adyen Webhook for listening to important events
**This step is crucial and mandatory** for Lago to receive and process messages from Adyen, enabling functionalities such as customer creation/update, payment processing, and refunds. To configure Adyen webhook and establish communication with Lago, follow the steps below:
1. Access your Adyen application and navigate to the **Developers** section;
2. Select **Webhooks** and create a new webhook of type **Standard**;
3. In the **Server configuration** section, locate the **General** settings; and
4. Copy and paste the following URL: **`https://api.getlago.com/webhooks/adyen/{{your_organization_id}}?code={{connection_code}}`**.
You can find your Organization ID in Lago under the Developers section in Lago, specifically in **API keys & ID** > **Organization ID**.
To find your **connection code**, navigate to the Integrations section in Lago and select the appropriate connection code for your Adyen integration.
**Please ensure that you complete this setup correctly, as your Adyen integration will not function without this vital step.**
## Setting Adyen as a Payment Provider for a customer
In order to facilitate automated payment collection, it is essential for the customer to exist in both the Lago and Adyen databases. Please note that in Adyen, customers are referred to as **Shoppers**.
### Adding a new customer in Adyen
If the customer does not already exist in Adyen, you can create them in Lago using either the user interface or the **[API](/api-reference/customers/create)**. When providing customer information, please ensure the following:
1. Set Adyen as the customer's **default payment provider**;
2. Keep the field associated with the **Adyen Payment Provider Customer ID** empty; and
3. **Enable** the option to automatically create the customer in Adyen.
Once the customer is added in Lago, they will be automatically synchronized with Adyen. Adyen will generate a unique Shopper ID, which will be stored in Lago. Typically, Adyen utilizes the Lago customer's **`external_id`** as the Shopper ID for seamless integration between the two platforms.
Upon successful customer creation, you will receive two **[webhook messages](/api-reference/webhooks/messages)** to keep you informed:
1. **`customer.checkout_url_generated`**: This message includes the checkout URL that provides access to the default payment method. It allows you to perform a pre-authorization payment and store the payment method securely; and
2. **`customer.payment_provider_created`**: This message confirms the successful creation of the customer in Adyen, indicating that the customer's details have been added to the Adyen database.
Please note that the customer will be created in Adyen only if the payment method has been stored through the checkout URL and pre-authorization payment.
### Using an existing customer from Adyen
If the customer and direct debit mandate already exist in Adyen, you can create the customer record in Lago using either the user interface or **[the API](/api-reference/customers/create)**. Follow these steps when adding customer information:
1. Set Adyen as the **default payment provider** for the customer in Lago; and
2. Provide the **Adyen [Shopper Reference](https://docs.adyen.com/point-of-sale/card-acquisition/identifiers#:~:text=Shopper%20reference%3A%20a,contract%20payments.)** as the Lago **Payment provider customer ID**.
3. **Disable** the option to automatically create the customer in Adyen.
By following these steps, you can integrate an existing customer from Adyen into Lago, ensuring synchronization and consistency between the two platforms.
## Adyen Checkout: storing customer's payment method information
When Lago automatically creates a customer in Adyen, you will receive a checkout link from Lago to facilitate the storage of your customer's payment method information.
The payload sent by Lago will have the following structure, with the checkout link stored under **`checkout_url`**:
```json
{
"webhook_type": "customer.checkout_url_generated",
"object_type": "payment_provider_customer_checkout_url",
"payment_provider_customer_checkout_url": {
"lago_customer_id": "88d23508-47fd-46bb-a87e-50c50f3cb371",
"external_customer_id": "hooli_1234",
"payment_provider": "adyen",
"checkout_url": "https://test.adyen.link/PLEEA656869B11DF6B"
}
}
```
Note: The checkout link automatically expires after 70 days.
By utilizing this provided checkout link, your customers can perform a pre-authorization payment. It's important to note that the pre-authorization payment will not collect any funds from the customer. Once the pre-authorization is confirmed, Lago will send the payment method details and securely store them into Adyen for future transactions.
## Creating payments from Lago Invoices
When a customer has Adyen defined as their payment provider, Lago seamlessly automates the process of triggering payments in Adyen whenever a new invoice is generated.
This integration ensures that payments are initiated in Adyen without any manual intervention. Lago's automatic payment creation saves time and effort, providing a streamlined experience for both you and your customers.
## Creating refunds from Lago Credit Notes
In cases where a customer has Adyen defined as their payment provider, Lago simplifies the refund process by automatically triggering refunds in Adyen whenever a new refund is initiated through credit notes.
This integration eliminates the need for manual refund processing and ensures that refunds are efficiently handled in Adyen. Lago's automated refund functionality helps you maintain accurate and timely refund transactions, enhancing customer satisfaction and operational efficiency.
## Payment disputes
In the event of a **lost** chargeback (dispute) within Adyen, Lago initiates an automatic response by marking the relevant invoice as disputed lost. This action involves populating the `dispute_lost_at` field with the timestamp when the dispute was lost. Following this update:
* The invoice becomes non-voidable;
* Generating a credit note is possible; however, refunding the payment back to the original payment method is not permitted; and
* The invoice cannot be resent for collection.
## Watch the demo video
# GoCardless integration
Lago's native integration with GoCardless allows you to collect payments via direct debit.
## Integration setup[](#integration-setup "Direct link to heading")
### Connect your GoCardless account[](#connect-your-gocardless-account "Direct link to heading")
To connect to GoCardless through the user interface:
1. In the side menu, select **"Settings"**;
2. Open the **"Integrations"** tab;
3. Select **"GoCardless"** to be redirected to the GoCardless application;
4. Create a GoCardless account or log in to your existing account; and
5. Connect your account to be redirected to the Lago application.
When the OAuth connection is active, you will see the screen below, with your
secret key.
### Create webhook endpoints[](#create-webhook-endpoints "Direct link to heading")
To complete this process, you will need:
* Your Lago **organization ID**, available in the **"API keys & ID"** tab of the
**"Developers"** section; and
* Your **secret key**, available in the **"Integrations"** tab of the
**"Settings"** section ([learn more](#connect-your-gocardless-account)).
If you want Lago to automatically retrieve the status of the payments processed
via GoCardless, you must create a webhook endpoint in GoCardless. To do so:
1. Log in to your [GoCardless account](https://manage.gocardless.com/sign-in);
2. Go to the **"Developers"** section;
3. In the upper right corner, click **"Create"** and then select **"Webhook endpoint"**;
4. Choose a name for this webhook (e.g. Lago);
5. Enter the following URL: `https://api.getlago.com/webhooks/gocardless/{{organization_id}}?code={{connection_code}}` (you must replace `{organization_id}` with your Lago organization ID, and the `{connection_code}` by the targeted Lago connection);
6. Enter your secret key; and
7. Click **"Create webhook endpoint"**.
In addition to this, you must create a webhook endpoint in Lago to retrieve the
checkout URL associated with each customer account
([learn more](#direct-debit)). To do so:
1. Go to the **"Developers"** section of the Lago application;
2. In the **"Webhooks"** tab, click **"Add a webhook"** on the right;
3. Enter your webhook URL; and
4. Click **"Add webhook"** to confirm.
For more information about our webhooks, please refer to the
[API documentation](/api-reference/webhooks/messages).
## Customer information[](#customer-information "Direct link to heading")
To collect payments automatically, the customer must exist in both the Lago and
GoCardless databases.
### New customer[](#new-customer "Direct link to heading")
If the customer does not already exist in GoCardless, you can first create them
in Lago, either via the user interface or
[the API](/api-reference/customers/create). When adding customer information, you
must:
1. Provide the customer's email address;
2. Define GoCardless as the **default payment provider**;
3. Leave the field associated with the **GoCardless customer ID** blank; and
4. **Enable** the option to automatically create the customer in GoCardless.
The customer will automatically be added to GoCardless. GoCardless will then
return the customer ID, which will be stored in Lago.
When the customer is successfully created, you will receive two
[webhook messages](/api-reference/webhooks/messages):
* `customer.payment_provider_created` that confirms the creation of the customer
in GoCardless; and
* `customer.checkout_url_generated` that includes the checkout URL to set up the
direct debit ([learn more](#direct-debit)).
### Existing customer[](#existing-customer "Direct link to heading")
If the customer and direct debit mandate already exist in GoCardless, then you
should create the customer record in Lago, either via the user interface or
[the API](/api-reference/customers/create). When adding customer information, you
must:
1. Provide the customer's email address;
2. Define GoCardless as the **default payment provider**;
3. Provide the **GoCardless customer ID**; and
4. **Disable** the option to automatically create the customer in GoCardless.
## Direct debit[](#direct-debit "Direct link to heading")
To collect payments via direct debit, a mandate must be created. To do so:
1. Retrieve the checkout URL included in the `customer.checkout_url_generated` webhook; and
2. Redirect your customer to the checkout page, so that they can complete the online form and approve the mandate.
The mandate must be validated by GoCardless before the first payment can be
processed. It can take up to six business days to validate a new mandate. For
more information about payment timings, please consult the
[GoCardless FAQ](https://gocardless.com/faq/merchants/direct-debit/).
To collect payments via direct debit, the currency of the mandate must match
the currency of the plan associated with the customer's subscription.
Each time a new invoice with an **amount greater than zero** is generated by
Lago, a payment will automatically be created. GoCardless will record the
invoice ID and process the payment. Payments via direct debit are usually
processed within five business days. If the payment is successful, the status of
the payment will switch from `pending` to `succeeded`.
If the payment fails, the status of the payment will switch from `pending` to
`failed` and Lago will generate an `invoice.payment_failure`
[webhook](/api-reference/webhooks/messages).
If you have signed up for [GoCardlessSuccess+](https://gocardless.com/solutions/success-plus/), failed payments may
be automatically resubmitted, in which case Lago will automatically update the
invoice payment status.
# Overview
Connect Lago to any payment providers by using native integrations or webhook messages.
Lago helps you monitor usage and calculates how much each customer owes you. However, **Lago is not a payment service provider (PSP)**.
## Payment collection process
To collect payments from your customers, you can:
* Use our native integrations with [GoCardless](/guide/payments/gocardless-integration), [Stripe Payments](/guide/payments/stripe-integration) or [Adyen](/guide/payments/adyen-integration); or
* Use the [webhooks](/api-reference/webhooks/messages) sent by Lago to transmit billing information to your PSP (e.g. Paddle, Razorpay, Authorize.net, internal ledger, etc.).
Lago is **agnostic**, which means that you can use our billing solution with any PSP.
## Payment status
When payments are processed through one of our native integrations, the payment status of the invoice is **automatically updated**.
If needed, you can update the payment status via the user interface:
1. Access the **"Invoices"** section;
2. Select an invoice from the list;
3. Open the **"Actions"** dropdown menu in the upper right corner;
4. Click **"Update payment status"**;
5. Select the new payment status; and
6. Click **"Update status"** to confirm.
This action can be performed [via the API](/api-reference/invoices/update) as well by changing the `payment_status` argument.
```bash Update a payment status of an invoice
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/invoices/{__INVOICE_ID__}" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"invoice": {
"payment_status": "succeeded",
"metadata": [
{...}
]
}
}'
```
## Handling one-off payments
Lago offers a streamlined solution for handling exceptional payment situations through its one-off payment checkout feature.
This is particularly useful when automatic payment processes face issues, resulting in invoices with `pending` or `failed` statuses.
* **Instant checkout link generation:**
For any troubled invoice, Lago enables you to generate a unique checkout link. This link can be shared with the user to facilitate an immediate payment of that invoice.
* **Automatic payment method storage:**
Lago captures and stores the payment method used in the one-off transaction. This ensures that future payments are processed more smoothly.
* **Real-time payment status update:**
The status of the invoice is updated in real time once the payment is successfully processed.
Currently, this feature is only supported for Adyen and Stripe native integrations with Lago.
# Payment retries
Whether you use one of our native integrations or rely on our
[webhooks](/api-reference/webhooks/messages) to collect payments, you have the ability to
manually resend payments for collection when needed.
To re-trigger the payment process through the user interface:
1. Access the **"Invoices"** section via the side menu;
2. Open the **"Outstanding"** tab;
3. Find the invoice for which you would like to collect payment;
4. Click the **ellipsis icon** on the right; and
5. Select **"Resend for collection"**.
In the **"Outstanding"** and **"Overdue"** tabs of the **"Invoices"** section, you can also
click **"Resend for collection"** in the upper right corner to re-trigger the
payment process for all invoices in the respective lists.
Invoices that are overdue are available both on the **"Outstanding"** and the
**"Overdue"** tabs. Make sure you resend for collection from the **"Overdue"**
tab if you wish to collect payment for past due invoices only.
When a payment is resent for collection, an `invoice.created` or
`invoice.add_on_added` webhook is automatically sent, depending on the type of
invoice.
In addition to this, if the default payment provider for the customer is
[Stripe](/guide/payments/stripe-integration),
[GoCardless](/guide/payments/gocardless-integration) or [Adyen](/guide/payments/adyen-integration), Lago will automatically process
the payment through integration.
It is also possible to trigger payment retries via the API
([learn more](/api-reference/invoices/retry.mdx)).
# Stripe integration
Lago's native integration with Stripe allows you to collect payments automatically when new invoices are generated.
## Watch the demo video
## Integration setup[](#integration-setup "Direct link to heading")
To set up the integration with Stripe through the user interface:
1. In the side menu, select **"Settings"**;
2. Select the **"Integrations"** tab;
3. Click **"Stripe"** and add a new connection;
4. Give this new connection a name and a code;
5. Enter your Stripe API key ([locate your API key](https://support.stripe.com/questions/locate-api-keys-in-the-dashboard)); and
6. Click **"Connect to Stripe"** to confirm.
By default, customers created in Lago are not automatically created in Stripe.
If you want your Lago customers to be added to Stripe, you need to activate
this option ([learn more](#new-customer)).
## Redirect url after checkout[](#checkout-redirect-url "Direct link to heading")
After establishing the connection with Stripe, set a success URL where your end customer will be directed after completing the checkout.
Please note that if it's not defined, your end customer will be redirected to Stripe's website.
Please note that you can edit or delete the redirect URL, and this will only affect new checkout URLs created.
URL defined should always begin with `http://` or `https://`.
## Customer information[](#customer-information "Direct link to heading")
To collect payments automatically, the customer must exist in both the Lago and
Stripe databases.
### New customer[](#new-customer "Direct link to heading")
If the customer does not already exist in Stripe, you can first create them in
Lago, either via the user interface or [the API](/api-reference/customers/create).
When adding customer information, you must:
1. Define Stripe as the **default payment provider**;
2. Leave the field associated with the **Stripe customer ID** blank;
3. **Enable** the option to automatically create the customer in Stripe; and
4. Define payment method options for this customer. Possible values are `card`, `link`, `sepa_debit`, `us_bank_account` and `bacs_debit`.
The customer will automatically be added to Stripe. Stripe will then return the
customer ID, which will be stored in Lago.
### Existing customer[](#existing-customer "Direct link to heading")
If the customer already exists in Stripe but not in Lago, you should create the
customer record, either via the user interface or
[the API](/api-reference/customers/create). When adding customer
information, you must:
1. Define Stripe as the **default payment provider**;
2. Provide the **Stripe customer ID**;
3. **Disable** the option to automatically create the customer in Stripe; and
4. Define payment method options for this customer. Possible values are `card`, `link`, `sepa_debit`, `us_bank_account` and `bacs_debit`.
## Supported payment methods
Lago's Stripe integration accommodates a variety of payment methods, both generic and region-specific.
The checkout URL provided by Lago is designed to handle multiple payment options seamlessly.
Lago's Stripe integration includes a universal card payment method that supports various currencies, ideal for global transactions.
This method is set as the default to facilitate recurring payments, ensuring Lago can process charges for your customers efficiently.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["card"]
}
}
}'
```
For European customers, Lago supports Stripe SEPA Debit (Single Euro Payments Area).
Accepting a mandate through this method authorizes you to debit your customers' accounts for recurring payments via Lago.
The designated payment method for SEPA transactions within Lago is identified as `sepa_debit`.
It's important to note that **this payment option is exclusive to invoices in `EUR` currency**.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["sepa_debit"]
}
}
}'
```
For US-based transactions, Lago integrates Stripe ACH Debit, leveraging the Automated Clearing House for electronic bank-to-bank payments.
Upon accepting a mandate, you gain authorization to execute recurring debits from your customers' accounts through Lago.
The designated payment method for ACH transactions within Lago is identified as `us_bank_account`.
It's important to note that **this payment option is exclusive to invoices in `USD` currency**.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["us_bank_account"]
}
}
}'
```
For UK transactions, Lago integrates Stripe BACS Debit, utilizing the UK's BACS system for direct bank-to-bank payments.
By accepting a mandate with this method, you're authorized to initiate recurring debits from your customers' accounts through Lago.
The specific payment method for BACS transactions within Lago is designated as `bacs_debit`.
It's important to note that **this payment method is exclusively for invoices in `GBP` currency.**
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["bacs_debit"]
}
}
}'
```
For card transactions, you can enable the [Link](https://stripe.com/payments/link) feature to offer one-click payments.
Link automatically fills in your customers' payment information, ensuring a seamless and secure checkout experience.
If you are using the `link` feature, it must be used in conjunction with `card`.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["card", "link"]
}
}
}'
```
## Stripe Checkout: storing customer's payment method information
Checkout page shows only selected payment methods for customers.
When Lago automatically creates a customer in Stripe, you will receive a checkout link from Lago to facilitate the storage of your customer's payment method information.
The payload sent by Lago will have the following structure, with the checkout link stored under `checkout_url`:
```json
{
"webhook_type": "customer.checkout_url_generated",
"object_type": "payment_provider_customer_checkout_url",
"payment_provider_customer_checkout_url": {
"lago_customer_id": "88d23508-47fd-46bb-a87e-50c50f3cb371",
"external_customer_id": "hooli_1234",
"payment_provider": "stripe",
"checkout_url": "https://checkout.stripe.com/c/pay/prod_c15sTbBMLep5FKOA9b9pZBiRBBYYSU1IJ5T89I5TTtpKgzE380JSmxnVYz#fidkdWxOYHw"
}
}
```
Note: The checkout link automatically expires after 24 hours!
By utilizing this provided checkout link, your customers can perform a pre-authorization payment. It's important to note that the pre-authorization payment will not collect any funds from the customer. Once the pre-authorization is confirmed, Lago will send the payment method details and securely store them into Stripe for future transactions.
## Regenerate checkout link on demand
In cases where your end customer has not had the opportunity to complete the checkout process to inform their payment method
or wishes to modify the saved payment information, you can generate a new checkout link using the designated [endpoint](/api-reference/customers/psp-checkout-url).
```bash
POST /api/v1/customers/:customer_external_id/checkout_url
```
Upon successful generation, the new checkout link will be available in the endpoint response, and it will not be delivered through a webhook message.
It is important to note that the new link will inherit the same expiration setting as the original one.
It is crucial to be aware that if a customer is not associated with any payment provider, the response will contain an error message.
## Default payment method
When you add a new payment method in Stripe, **Lago automatically sets it as the default**.
This guarantees that Lago uses the latest payment method for a customer. However, if you manually designate one of
multiple payment methods as the default, Lago will use it for payments instead the most recent one.
## Payment intents[](#payment-intents "Direct link to heading")
Once Stripe is connected and the customer exists in both databases, you can
start collecting payments.
### Succeeded payments
Each time a new invoice with an **amount greater than zero** is generated by
Lago, a payment intent will automatically be created. Stripe will record the
invoice ID and process the payment. If the payment is successful, the status of
the payment will switch from `pending` to `succeeded`.
### Failed payments
If the payment fails, the status of the payment will switch from `pending` to
`failed` and Lago will generate an `invoice.payment_failure`
[webhook](/api-reference/webhooks/messages).
### Payments requiring validation
When a payment requires multi-step authentication, such as 3D Secure (3DS), Lago triggers a `payment.requires_action` [webhook](/api-reference/webhooks/messages#payment-requires-action).
This webhook provides the URL for completing the 3DS process. It's important to note that **most payments in India require 3DS authentication** due to [RBI regulations](https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=12051\&Mode=0).
### Minimum payment amount
If the new invoice amount falls below the [minimum amount supported by Stripe](https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts), the payment status will remain as `pending`.
A valid payment method for the customer must be defined in Stripe for the
payment intent to succeed ([learn how to save payment
details](https://stripe.com/docs/payments/save-and-reuse)).
## Payment disputes
In the event of a **lost** payment dispute within Stripe, Lago initiates an automatic response by marking the relevant invoice as disputed lost. This action involves populating the `dispute_lost_at` field with the timestamp when the dispute was lost. Following this update:
* The invoice becomes non-voidable;
* Generating a credit note is possible; however, refunding the payment back to the original payment method is not permitted; and
* The invoice cannot be resent for collection.
# Arrears vs Advance
Usage-based charges can be either charged in advance or in arrears
You have the flexibility to define the nature of charges associated with your products or services. Specifically, you can
**determine whether a charge has to be paid in arrears (at the end of the period), or in advance (immediately on event ingestion)**.
## Charges paid in arrears[](#charges-arrears "Direct link to heading")
If you opt for charges to be settled in arrears, they will be invoiced at the end of the billing period based on
the actual usage during that period. This payment option is ideal for usage types like storage, API calls, or compute,
where it is more practical to wait until the end of the period before billing. By default, all charges are configured to be
billed in arrears.
You can easily manage this billing settings through the user interface. Within the UI, you will find options to customize
the invoice cadence by setting a charge as invoiced in arrears.
Define `pay_in_advance : false` on a charge to bill it in arrears:
```bash Define a charge as paid in arrears {16, 22}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Premium",
"code": "premium",
"interval": "monthly",
"description": "Premium plan for SMB companies",
"amount_cents": 50000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"bill_charges_monthly": true,
"charges": [
{
"billable_metric_id": "1111_2222_3333_4444",
"charge_model": "percentage",
"pay_in_advance": false,
"invoiceable": true,
"min_amount_cents": 100,
"properties": {
"rate": "0.5",
"fixed_amount": "1",
"free_units_per_events": 3,
"free_units_per_total_aggregation": null
}
}
]
}
}'
```
## Charges paid in advance[](#charges-advance "Direct link to heading")
With this payment option, charges are invoiced immediately upon any changes in usage. It is particularly useful for scenarios
where you need to bill customers instantly for usage-based actions, such as new user seat or integrations.
You can easily manage this billing settings through the user interface. Within the UI, you will find options to customize
the invoice cadence by setting a charge as invoiced in arrears.
Define `pay_in_advance : true` on a charge to bill it in advance:
```bash Define a charge as paid in advance {16, 22}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Premium",
"code": "premium",
"interval": "monthly",
"description": "Premium plan for SMB companies",
"amount_cents": 50000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"bill_charges_monthly": true,
"charges": [
{
"billable_metric_id": "1111_2222_3333_4444",
"charge_model": "percentage",
"pay_in_advance": true,
"invoiceable": true,
"min_amount_cents": 100,
"properties": {
"rate": "0.5",
"fixed_amount": "1",
"free_units_per_events": 3,
"free_units_per_total_aggregation": null
}
}
]
}
}'
```
# Custom price
**Premium feature ✨**:
This feature is only available to users with a premium license. Please **[contact us](mailto:hello@getlago.com)** to get access this feature.
Lago's basic interface and API allow you to configure prices using default price models, such as standard, graduated, or percentage-based models.
However, for more sophisticated products, you may need more complex pricing capabilities than those offered by Lago's default settings.
To meet this need, Lago can parse your custom code (using JSON), enabling you to implement advanced pricing rules for your charges.
This feature provides the flexibility to create tailored pricing models that precisely fit your product's requirements.
By leveraging custom code, you can ensure your pricing strategy is as dynamic and nuanced as your product demands.
This custom pricing can be set using the `custom_properties` attribute for a specific charge.
You can edit this custom price code and even overwrite it for a particular subscription.
Here is an example of a custom price model defining tiers across multiple properties:
```json
"properties": {
"custom_properties": {
"ranges": [
{ "from": 0, "to": 10, "storage_eu": "0", "storage_us": "0", "storage_asia": "0" },
{ "from": 10, "to": 20, "storage_eu": "0.10", "storage_us": "0.20", "storage_asia": "0.30" },
{ "from": 20, "to": null," storage_eu": "0.20", "storage_us": "0.30", "storage_asia": "0.40" }
]
}
}
```
# Dynamic
Only the `sum` aggregation type is compatible with the `dynamic` charge model.
If you have a different use case, please reach out to the Lago team for assistance.
Select the dynamic charge model if you calculate the price manually or if prices fluctuate during a billing period (e.g., for SMS APIs, AI models, etc.), and you want to apply a specific **total amount** per event using the property `precise_total_amount_cents`.
Let’s take the example of our AI company. You may want to charge a custom price per event. Consider the following list of events:
| Event | Metric | Unit | Total amount |
| ------------- | ------------------ | ---- | ------------ |
| Transaction 1 | Dedicated Instance | 7 | \$0.70 |
| Transaction 2 | Dedicated Instance | 5 | \$0.55 |
| Transaction 3 | Dedicated Instance | 10 | \$2.20 |
```bash List of events
{
"events": [
{
"transaction_id": "transaction_1",
"external_subscription_id": "123456789",
"code": "dedicated_instance",
"timestamp": 1728554400,
"precise_total_amount_cents": "70", //event total amount
"properties": {
"unit": "7"
}
},
{
"transaction_id": "transaction_2",
"external_subscription_id": "123456789",
"code": "dedicated_instance",
"timestamp": 1728558000,
"precise_total_amount_cents": "55", //event total amount
"properties": {
"unit": "5"
}
},
{
"transaction_id": "transaction_3",
"external_subscription_id": "123456789",
"code": "dedicated_instance",
"timestamp": 1728561600,
"precise_total_amount_cents": "220", //event total amount
"properties": {
"unit": "10"
}
}
]
}'
```
At the end of the period, the invoice will generate **one fee of \$3.435** (see example bellow).
| Item | Unit | Unit price | Amount |
| ------------------ | ---- | ---------- | ------ |
| Dedicated Instance | 22 | \$0,156818 | \$3.45 |
To display more detailed information on fees, please refer to the [custom invoice grouping](/guide/invoicing/overview#custom-invoice-grouping) or the [pay in advance](/guide/plans/charges/arrears-vs-advance#charges-paid-in-advance) option.
Only the `standard` & `dynamic` charge models support the [custom invoice grouping](/guide/invoicing/overview#custom-invoice-grouping).
# Graduated
Select the graduated charge model if you want to define **several price tiers**.
This charge model allows you to apply a discount depending on the number of
units consumed. You can also apply a **flat fee** to an entire tier.
Let's take back the example of the API company. You could charge \$1 per unit for
the first 100 units (first 100 API calls), then \$0.50 per unit for the next 100
calls and finally, \$0.10 for any additional unit.
Please refer to the tooltip in the user interface for more information.
# Graduated percentage
Select the graduated percentage model if you want to define several percentage tiers. You can also
apply a **flat fee** per tier in addition to the rate.
Note that the **rate** is the only mandatory value. It's particularly useful for fintech charging graduated rates for a feature.
Consider the following example, where each unit represents an API call:
| Tier | First unit | Last unit | Rate | Flat fee |
| ------ | ---------- | --------- | ---- | -------- |
| Tier 1 | 0 | 1,000 | 1% | \$200 |
| Tier 2 | 1,001 | 10,000 | 2% | \$300 |
| Tier 3 | 10,001 | ∞ | 3% | \$400 |
A first transaction at \$500 would cost (500 units x 1%) + \$200 flat fee = \$205.00;
A second transaction at \$550 would cost \[(500 units x 1%) + (50 units x 2%)] + \$300 flat fee = \$306.00;
A third transaction at \$4,000 would cost (4,000 x 2%) = \$80.00.
Unlike the fixed fee, **the flat fee is applied to the entire tier**, rather than per transaction.
# Package
Select the package charge model if you want to apply a **fixed price to a range
of units**. You also have the ability to offer free units.
Let's take back the example of our API company. You may want to charge \$5 per
100 units and offer the first 100 units. In this example, 201 units would cost
\$0 (first 100 units) + \$5 (next 100 units) + \$5 (last unit) = \$10.
# Percentage
Select the percentage charge model if you want to apply a **percentage and a
fixed fee on transactions** (e.g. bank transfers, ATM withdrawals, etc.).
This charge model is generally used with billable metrics that allow users to
calculate the total amount of transactions (e.g. `sum` aggregation type and
`amount` defined as the event property -
[learn more](/guide/billable-metrics/aggregation-types)).
You can define several parameters for the percentage charge model, including:
* **Percentage rate**: charge rate that applies to the total amount (e.g. 1.2%
on transactions);
* **Fixed fee (optional)**: fee that applies to each event ingested during the
billing period (e.g. \$0.10 per transaction);
* **Free units (per event - optional)**: number of events that are not subject to
the fixed fee;
* **Free units (total amount - optional)**: amount that is not subject to the
charge rate;
* **Per-transaction spending minimum (per event - optional)**: sets the minimum amount of spending required for each individual transaction; and
* **Per-transaction spending maximum (per event - optional)**: sets the maximum amount of spending required for each individual transaction.
When free units are defined for both the total amount and number of events, Lago
performs checks each time a new event is ingested to determine whether the free
units still apply. In the illustration below for instance, the first 3 events or
\$500 are free.
**Premium feature ✨**: only users with a premium license can define a per-transaction spending minimum and maximum for the percentage pricing model.
Please **[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago Self-Hosted Premium.
Consider the following list of events:
| Event | Amount | Total number of events | Total amount | Result |
| ------------- | ------ | ------------------------------ | ------------------ | ---------- |
| Transaction 1 | \$200 | 1 free event (out of 3) | \$200 (\$500 free) | No charges |
| Transaction 2 | \$100 | 2 free events (out of 3) | \$300 (\$500 free) | No charges |
| Transaction 3 | \$100 | 3 free events (out of 3) | \$400 (\$500 free) | No charges |
| Transaction 4 | \$50 | 4 events (free units exceeded) | \$450 (\$500 free) | Charge |
Therefore, for the fourth transaction, the charge will be \$0.10 x 1 event + 1.2%
of \$50 = \$0.70.
# Standard
Select the standard charge model if you want to charge the **same price for each
unit** consumed.
Imagine that your API company charges \$0.05 per API call (i.e. your billable
metric). By selecting the standard charge model, you will define a fixed unit
price. If a customer makes 1,000 API calls during the billing period, the total
invoice amount will be \$0.05 x 1,000 API calls = \$50.
Only the `standard` & `dynamic` charge models support the [custom invoice grouping](/guide/invoicing/overview#custom-invoice-grouping).
# Volume
Select the volume charge model if you want to define several price tiers but
want to apply a **single unit price based on the total volume**. You can also
apply a **flat fee** in addition to the unit price.
Consider the following example, where each unit represents an API call:
| Tier | First unit | Last unit | Unit price | Fixed fee |
| ------ | ---------- | --------- | ---------- | --------- |
| Tier 1 | 0 | 10,000 | \$0.0010 | \$10 |
| Tier 2 | 10,001 | 50,000 | \$0.0008 | \$10 |
| Tier 3 | 50,001 | 100,000 | \$0.0006 | \$10 |
| Tier 4 | 100,001 | ∞ | \$0.0004 | \$10 |
In this case, 65,000 API calls would cost 65,000 x \$0.0006 + \$10 = \$49.
# Charges with filters
Charge your customers by leveraging a combination of filters specified in the billable metric.
## Define a price for a combination of filters[](#define-price-for-filters "Direct link to heading")
When a billable metric has defined filters, establish a set of filters to refine an event and assign a price to this combination.
1. Add a charge to a plan (this charge should be associated with a billable metric containing filters);
2. Add a new filter;
3. Choose a combination of filters, either specifying a key and its value or simply the key itself (covering all values);
4. Set a price for this combination of filters; and
5. Optionally, provide an Invoice display name.
Here are an example of plans you can create:
```bash Charge with filters {22-43}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Standard plan",
"code": "standard_plan",
"interval": "monthly",
"pay_in_advance": false,
"amount_cents": 1000,
"amount_currency": "USD",
"charges": [
{
"billable_metric_id": "5d387072-e1f2-416f-b981-135c2f177069",
"invoice_display_name": null,
"charge_model": "standard",
"properties": {
"amount": "2"
},
"filters": [
{
"values": {
"region": ["africa"],
"provider": ["aws"]
},
"invoice_display_name": "Africa & AWS",
"properties": {
"amount": "1"
}
},
{
"values": {
"region": ["__ALL_FILTER_VALUES__"],
"provider": ["__ALL_FILTER_VALUES__"]
},
"invoice_display_name": "Other regions and providers",
"properties": {
"amount": "0.5"
}
}
]
}
]
}'
```
## Define a default price[](#define-default-price "Direct link to heading")
When a billable metric has filters defined, set a default price on the charge level to cover all the other combination of filters not defined in the charge.
1. Add a charge to a plan (this charge should be associated with a billable metric containing filters);
2. Add a default price;
3. Set a price for this default price
Here are an example of plans you can create:
```bash Storage
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "Standard plan",
"code": "standard_plan",
"interval": "monthly",
"pay_in_advance": false,
"amount_cents": 1000,
"amount_currency": "USD",
"charges": [
{
"billable_metric_id": "5d387072-e1f2-416f-b981-135c2f177069",
"invoice_display_name": null,
"charge_model": "standard",
"properties": {
"amount": "2"
}
}
]
}'
```
If the default price is not set, Lago will automatically define it as 0 based on the charge model.
# Invoiceable vs Uninvoiceable
In-advance charges can be either invoiceable or not.
**Premium feature ✨**: only users with a premium license can define whether
or not a charge is invoiceable. Please **[contact
us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
If a charge needs to be `paid in advance`, you can choose whether or not it generates an invoice.
The `"invoiceable": false` option is **particularly relevant for fintech companies that want to charge customers instantly
without issuing an invoice**. This feature can be useful for banking transactions like ATM withdrawals, FX transfers and other
similar scenarios.
By setting the invoiceable parameter to false, a fee is created by default, and a webhook `fee.created` is sent immediately upon any changes in usage without generating an invoice. However, you can configure the charge invoicing strategy via `regroup_paid_fees`:
1. `null`: Fees generated never appear on invoices (default behaviour).
2. `invoice`: Groups all paid fees into one invoice at the end of the billing period.
Please note that if `invoice`, all fees generated with a `payment_status` different from `succeeded` won’t appear on invoice generated at the end of the billing period. They will appear on next ones if you manually edit their `payment_status` to `succeeded`.
The invoice generated consolidates paid fees, is marked as paid, and will not be emailed to your end customer if the email feature is activated.
1. Go to a **Plan**;
2. Add a usage-based **charge**;
3. Define a price model;
4. Define this charge as **paid in advance**; and
5. Select the option that best suits your needs from the three available choices.
Use the `invoiceable : false` for a charge paid in advance:
```bash Define a charge as invoiceable or not {23}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Premium",
"code": "premium",
"interval": "monthly",
"description": "Premium plan for SMB companies",
"amount_cents": 50000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"bill_charges_monthly": true,
"charges": [
{
"billable_metric_id": "1111_2222_3333_4444",
"charge_model": "percentage",
"pay_in_advance": true,
"invoiceable": false,
"regroup_paid_fees" : "invoice"
"min_amount_cents": 100,
"properties": {
"rate": "0.5",
"fixed_amount": "1",
"free_units_per_events": 3,
"free_units_per_total_aggregation": null
}
}
]
}
}'
```
# Metered vs Recurring
Usage-based charges can be either metered or recurring
You have the flexibility to define the nature of charges associated with your products or services. Specifically, you can
**determine whether a charge is metered or recurring**. Understanding the distinction between these two types of charges is crucial for
effectively managing your billing processes. In this documentation, we will delve into the differences between metered and
recurring charges and their implications within the Lago system.
## Metered charges[](#metered "Direct link to heading")
When you create a metered billable metric in Lago by setting the `recurring` parameter to `false`, an important behavior comes into play.
At the end of each billing period, the accumulated number of units associated with the metric is automatically reset to 0.
This means that the counting or measuring of units starts fresh with each new billing cycle. This is ideal for billing components with results
that are not persisted billing periods over billing periods.
In the API tab beside, consider the example of a **Storage billing unit**. If you need to **track the Gigabytes stored during a month**,
it's important to note that this value should be reset to 0 at the beginning of each new month.
Create a billable metric with `recurring` sets to `false`.
```bash Metered billable metric {13}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Storage",
"code": "storage",
"description": "GB of storage used in my application",
"aggregation_type": "sum_agg",
"recurring": false,
"field_name": "gb",
"group": {
"key": "region",
"value": ["us-east-1", "us-east-2", "eu-west-1"]
}
}
}'
```
## Recurring charges[](#recurring "Direct link to heading")
When you create a recurring billable metric in Lago with the recurring parameter set to true, an important behavior comes
into effect. At the end of each billing period, the accumulated number of units calculated from the previous billing period is
carried forward to the next billing period.
This means that the counting or measurement of units starts based on the last recorded value from the previous billing cycle.
This behavior is particularly useful for billing components or services where the results need to persist from one billing period
to another.
In the API tab, let's consider the example of a **Seats billing unit**. If you need to **track the number of active seats**, it's crucial to
note that this value should persist month over month. The recurring billing behavior ensures that the count of active seats is
maintained and carried forward to subsequent billing periods, providing accurate and continuous tracking of your subscription seats.
Create a billable metric with `recurring` sets to `true`.
```bash Recurring billable metric {13}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Seats",
"code": "seats",
"description": "Active seats.",
"aggregation_type": "count_unique",
"recurring": true,
"field_name": "seat_id",
"group": {
"key": "type",
"value": ["admin", "viewer", "editor"]
}
}
}'
```
# Overview
In addition to the price of the plan, you can charge your customers for usage.
## Overview of charges[](#overview-of-charges "Direct link to heading")
To incorporate usage-based charges into a plan, you can utilize existing billable metrics.
This enables you to offer "pay-as-you-go" features.
For instance, you can create charges based on the number of API calls, the
number of active users, transactions, compute time, etc. These additional
charges relate to the [billable metrics](/guide/billable-metrics/create-billable-metrics) defined previously.
Here are some important details to consider regarding usage-based charges:
## Currency of charges[](#charges-currency "Direct link to heading")
All charges are denominated in the same currency as the plan to ensure consistency and transparency.
## Trial period exclusions[](#trial-period-exclusion "Direct link to heading")
It's important to note that the trial period exclusively applies to the base amount of the plan and does not extend
to usage-based charges.
## Number of decimals[](#number-of-decimals "Direct link to heading")
Lago allows you create charges with up to fifteen decimals (e.g.
\$0.000123456789123).
Please note that charges are invoiced in `amount_cents`. Therefore, Lago
automatically rounds prices (e.g. USD 1102 `amount_cents` = \$11.02).
## Delete a charge[](#delete-charge "Direct link to heading")
You may delete a charge included in a plan associated with existing
[subscriptions](/guide/subscriptions/assign-plan).
If you do so and save the change:
* The charge will be immediately removed from all subscriptions linked to this
plan;
* The charge will no longer be included in the
[current usage](/api-reference/customer-usage/customer-usage-object) of the customers
concerned; and
* The charge will be immediately removed from all `draft` invoices associated
with these subscriptions.
However, the charge will still be included in all `finalized` invoices
associated with these subscriptions.
Deleting a charge does not delete the events associated with the corresponding
billable metric. If later you decide to add the charge back into the plan, the
events received before the deletion may be taken into account in the billing
process (depending on the limits of the billing period).
## Update invoice display names[](#invoice-display-names "Direct link to heading")
When creating or updating a charge within our system, you have the flexibility to customize the way it
appears by overriding its default name. This can be achieved by defining an `invoice display name` for the charge.
By doing so, the newly specified name will take precedence and be reflected across all relevant contexts,
including prominently on the invoice template.
# Prorated vs Full
Usage-based charges can be either bill fully or prorated based on the number of days used.
You can **determine whether a charge is prorated or fully-billed**. Understanding the distinction between these two types of
charges is crucial for effectively managing your billing processes. In this documentation, we will delve into the differences
between prorated and fully-billed charges and their implications within the Lago system.
## Prorated charges[](#prorated "Direct link to heading")
Only charges that are [recurring](#2-recurring-charges) (billable metric with `recurring` argument sets to `true`) with a `charge_model` defined to `standard`, `graduated` or `volume` can be prorated.
When creating a prorated charge in Lago with the `prorated` parameter set to `true`, an important behavior is triggered.
Adding a new unit during the billing period results in the amount due for that unit being prorated based on the number of
days it was used.
This means that your customers will only be charged for the actual number of days they utilized a billing unit. Let's **consider
the example of prorated `Seats`**, where each seat costs \$10. If a new seat is added on June 10th, the unit will be prorated for 22 days, resulting in a corresponding prorated charge for that duration. This ensures fair and accurate billing based on the
usage period.
*Example: (1 Seat x \$10), used for 22 days = \$7.33*
By leveraging prorated charges in Lago, you can provide transparent and cost-effective billing for services that are added or
removed mid-billing cycle, adjusting the charges according to the actual duration of usage.
Create a charge that is prorated by setting `prorated` to `true`.
Only charges that are [recurring](#2-recurring-charges) (billable metric with `recurring` argument sets to `true`) with a `charge_model` defined to `standard` or `volume` can be prorated.
```bash Prorated charges {25}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Startup",
"code": "startup",
"interval": "monthly",
"description": "This is a basic plan description",
"amount_cents": 10000,
"amount_currency": "USD",
"trial_period": 3.0,
"pay_in_advance": true,
"bill_charges_monthly": false,
"charges": [
{
"billable_metric_id": "__BILLABLE_METRIC_ID__",
"charge_model": "standard",
"pay_in_advance": true,
"invoiceable": true,
"min_amount_cents": 0,
"prorated": true,
"group_properties": [
{
"group_id": "__GROUP_ID__",
"values": {
"amount": "10"
}
}
]
}
]
}
}'
```
## Fully-billed charges[](#fully-billed "Direct link to heading")
Note that metered charges (billable metrics with `recurring` sets to `false`) are automatically fully-billed.
When creating a fully-billed charge in Lago with the `prorated` parameter set to `false`, an important behavior occurs.
If a new unit is added during the billing period, the amount due for that unit is billed in full, regardless of the number of
days it was used.
This means that your customers will be charged for the entire billing period, even if they only utilized the billing unit for a
few days. **Let's consider the example of fully-billed Seats**, where each seat costs \$10. If a new seat is added on June 10th, it will
be billed for the full billing period. For instance, if there is one seat that was used for 22 days in the billing period, the
charge would be calculated as follows:
*(1 Seat x \$10), used for 22 days = \$10.*
By utilizing fully-billed charges in Lago, you ensure that you do not lose revenue by billing customers for the entire billing period,
regardless of the actual duration of usage.
Create a charge that is billed fully by setting `prorated` to `false`.
```bash Fully-billed charges {25}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Startup",
"code": "startup",
"interval": "monthly",
"description": "This is a basic plan description",
"amount_cents": 10000,
"amount_currency": "USD",
"trial_period": 3.0,
"pay_in_advance": true,
"bill_charges_monthly": false,
"charges": [
{
"billable_metric_id": "__BILLABLE_METRIC_ID__",
"charge_model": "standard",
"pay_in_advance": true,
"invoiceable": true,
"min_amount_cents": 0,
"prorated": false,
"group_properties": [
{
"group_id": "__GROUP_ID__",
"values": {
"amount": "10"
}
}
]
}
]
}
}'
```
# Spending minimums
**Premium feature ✨**: only users with a premium license can define a charge spending minimum.
Please **[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago Self-Hosted Premium.
Usage-based charges are always paid at the end of the billing period, based on the amount of consumption that occurred. However, you
could possibly need to define a spending minimum that a customer needs to commit to.
If your customer spends less than the committed amount, you will **charge a true-up fee equal to the difference between the commitment
and the actual usage**. Please note that this true-up fee is tied to the initial charge but will appear as a separate line item in an
invoice or in a credit note.
**Spending minimums and true-up fees are always prorated based on the number of days used in the subscription**. This ensures
fairness if your customer signs up at the end of the month, upgrades to a new plan, or terminates an ongoing subscription
before the end of the period.
In the example below, a customer is billed based on Monthly Tracked Users (MTU), with a standard pricing of \$0.010 per tracked users.
However, the customer is committed to a spending minimum of \$100. If the total consumption of MTUs for the period is \$50, a true-up fee
of \$50 will be charged.
To define a charge spending minimum:
1. Go to a **Plan**;
2. Add a usage-based **charge**;
3. Define a price model;
4. Click the add a **spending minimum** button; and
5. Define a spending minimum **amount**.
Use the `min_amount_cents` field on a charge:
```bash Spending minimum for a charge {24}
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Premium",
"code": "premium",
"interval": "monthly",
"description": "Premium plan for SMB companies",
"amount_cents": 50000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"bill_charges_monthly": true,
"charges": [
{
"billable_metric_id": "1111_2222_3333_4444",
"charge_model": "percentage",
"pay_in_advance": false,
"invoiceable": true,
"min_amount_cents": 100,
"properties": {
"rate": "0.5",
"fixed_amount": "1",
"free_units_per_events": 3,
"free_units_per_total_aggregation": null
}
}
]
}
}'
```
# Commitments
**Premium feature ✨**:
This feature is only available to users with a premium license. Please **[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago Self-Hosted Premium.
In your plan configuration, Lago provides the flexibility to define specific spending commitments tailored to your business needs.
These commitments serve as a financial baseline for the services you offer. However, understanding the unique requirements of each customer,
Lago offers the capability to customize these commitments on a per-customer basis at the time of creating a subscription.
## Minimum commitment
### Guidelines
Besides setting [spending minimums per charge](/guide/plans/charges/spending-minimum), Lago also allows you to define minimum invoice totals.
This ensures customers meet a minimum spend per billing period, securing a steady revenue flow and aiding in accurate financial forecasting.
The minimum commitment per invoice set in Lago applies to all charges.
* **Commitment interval:** The minimum commitment is aligned with the billing interval of the plan. For instance, if the plan is billed monthly, the minimum commitment is also established on a monthly basis;
* **Customizable commitments:** When assigning a plan to a customer, you have the option to override the default commitment. This allows for customized minimum commitments per customer, accommodating negotiated contract terms; and
* **Arrears calculation:** The commitment is calculated in arrears, meaning Lago waits until the end of the billing period to assess whether users have met their minimum spending commitment. This approach ensures accurate billing based on actual usage.
### True-up fee
If the total spending falls below the minimum commitment at the end of the billing period, Lago will **apply a true-up fee to adjust the invoice and meet the minimum spending requirement**.
Conversely, if spending exceeds the minimum commitment, Lago will generate an invoice for the actual consumption, without issuing a true-up fee.
The minimum commitment is calculated based on the pre-tax amount and before any discounts (such as coupons or credits) are applied.
### Defining a minimum commitment
To create or update a minimum commitment from the user interface:
1. Access an existing or a new plan **"Plan"**;
2. Navigate below usage based charges;
3. Define a **minimum commitment**; and
4. Click **"Add plan"** to confirm.
The minimum commitment must follow the plan's interval. You can add a specific tax rate for this minimum commitment.
```json Define a minimum commitment {16-22}
{
"plan": {
"name": "Basic",
"invoice_display_name": null,
"created_at": "2024-02-23T16:01:04Z",
"code": "basic",
"interval": "monthly",
"description": "",
"amount_cents": 10000,
"pay_in_advance": true,
"bill_charges_monthly": null,
"customers_count": 2,
"active_subscriptions_count": 2,
"draft_invoices_count": 0,
"parent_id": null,
"minimum_commitment": {
"plan_code": "basic",
"invoice_display_name": "Minimum Contract Commitment",
"amount_cents": 50000,
"interval": "monthly",
"taxes": []
},
"charges": [
{
"id": "ca205886-cf09-4e42-aed6-34cb2afd0c29",
"billable_metric_id": "5b320600-715b-4ef5-88c1-4f88c0ec5c50",
"invoice_display_name": "",
"billable_metric_code": "storage",
"created_at": "2024-02-23T16:01:04Z",
"charge_model": "standard",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"properties": {
"amount": "1"
},
"group_properties": [],
"taxes": []
},
{
"id": "1d5c78c6-0e22-424f-af8d-6784f6ff44ec",
"billable_metric_id": "4cbc5940-32fb-48a8-aa39-ad664b34a062",
"invoice_display_name": null,
"billable_metric_code": "seats",
"created_at": "2024-02-23T16:04:09Z",
"charge_model": "standard",
"invoiceable": true,
"pay_in_advance": true,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"amount": "7"
},
"group_properties": [],
"taxes": []
}
],
"taxes": []
}
}
```
### Overwriting a minimum commitment
To overwrite the minimum commitment for a specific customer, follow these instructions:
1. Access a specific customer;
2. Choose to assign a new plan or edit an existing subscription; and
3. Override the default plan's minimum commitment with a new value.
```json Define a minimum commitment
{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "premium",
"name": "Repository A",
"external_id": "my_sub_1234567890",
"billing_time": "anniversary",
"subscription_at": "2022-08-08T00:00:00Z",
"plan_overrides": {
"amount_cents": 10000,
"amount_currency": "USD",
"description": "Plan for early stage startups.",
"invoice_display_name": "Startup plan",
"name": "Startup",
"tax_codes": [],
"minimum_commitment": {
"plan_code": "basic",
"invoice_display_name": "Minimum Contract Commitment",
"amount_cents": 50000,
"interval": "monthly",
"taxes": []
}
"charges": []
}
}
}
```
# Overview
If Billable metrics are made to measure customer usage, Plans are made to apply prices to this usage.
Note that you don't need to define a Billable metric to create a Plan. However,
if you have usage feature to charge, the price of your Billable metrics is
defined inside each Plan. Make sure to understand
[how to create a Billable metric](/guide/billable-metrics/create-billable-metrics) first.
## Plan structure[](#plan-structure "Direct link to heading")
A Plan defines the features your customers have access to, the prices paid to
access them and the invoicing cadence. In order to invoice a Customer with Lago,
you must assign a Plan to a customer.
**But first, let's define the structure of a Plan:**
1. [The Plan basic informations](#plan-structure)
* A Plan `name`
* A Plan `code`
* A Plan `description`
2. [The Plan model](/guide/plans/plan-model)
* A Plan `interval`
* A Plan base `amount` with the `currency`
* Boolean to define if the Plan is paid **in advance** or **in arrears**
* A Plan `trial period` in days
* Taxes applied to this plan
3. [The additional charges](/guide/plans/charges) for this Plan (any Billable metrics
that have been created)
* A Charge `model`
* A Charge `amount` and its `currency` (automatically inherited from the
currency of the Plan)
* A Charge spending minimum
* Boolean to define if the Charge is paid **in advance** or **in arrears**
* Taxes applied to this charge (overriding the one defined on the plan)
```bash Premium Plan Example
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Premium",
"code": "premium",
"interval": "monthly",
"description": "Premium plan for SMB customers",
"amount_cents": 50000,
"amount_currency": "USD",
"trial_period": 3.0,
"pay_in_advance": true,
"bill_charges_monthly": true,
"tax_codes": ["french_standard_vat"],
"charges": [
{
"billable_metric_id": "__BILLABLE_METRIC_ID__",
"charge_model": "graduated",
"pay_in_advance": false,
"invoiceable": true,
"min_amount_cents": 0,
"tax_codes": ["french_standard_vat"],
"properties": {
"graduated_ranges": [
{
"to_value": 10,
"from_value": 0,
"flat_amount": "0",
"per_unit_amount": "0.001"
},
{
"to_value": null,
"from_value": 11,
"flat_amount": "0",
"per_unit_amount": "0.0005"
}
]
}
}
]
}
}'
```
## Editing Plans[](#editing-plans "Direct link to heading")
Plans can be fully edited as long as they are not linked to a customer (i.e., no active [subscriptions](/guide/subscriptions/assign-plan)). Once a plan is assigned to a customer, you can modify subscription prices, add or remove charges, and adjust them. However, other settings—such as the “plan interval,” “pay in advance” options, and pro-rated charges—become fixed and cannot be edited once assigned to a customer.
Any edits to a plan will instantly impact all subscriptions linked to it.
Please note: If this plan is linked to overridden subscriptions, you can choose to cascade or not these changes to these overridden subscriptions.
When updating a plan via the API, use the `cascade_updates: true` property to ensure that overridden subscriptions are impacted by the changes.
To update plans that are already linked to customers, you will need to either remove all active subscriptions or create a new plan.
To update a specific charge in a plan, the charge must first be removed, then re-added with the updated details.
## Deleting Plans[](#deleting-plans "Direct link to heading")
Plans can be deleted regardless of whether they are linked to a subscription.
Deleting a plan that is linked to a subscription will automatically terminate the subscription, and invoices will be generated.
# Plan model
The plan model defines when and how much a customer is charged.
## Plan interval[](#plan-interval "Direct link to heading")
The plan interval corresponds to the billing period and defines when invoices
are generated. In most cases, the [charges](/guide/plans/charges) are also calculated
according to the plan interval.
There are several plan intervals:
1. **Weekly**: subscription fees and charges are billed on a weekly basis
(Monday to Sunday);
2. **Monthly**: subscription fees and charges are billed on a monthly basis;
3. **Quarterly**: subscription fees and charges are billed on a quarterly basis (every 3 months); and
4. **Yearly**: subscription fees are billed on a yearly basis and charges can be
billed monthly or annually.
## The base charge amount and its currency[](#the-base-charge-amount-and-its-currency "Direct link to heading")
You need to define a **base amount** for each plan (i.e. the subscription fee).
This amount is what the customer will pay by subscribing to the plan regardless
of their consumption.
This base charge `amount` is recurring, and billed at the end of each billing
interval.
## Pay in advance or in arrears[](#pay-in-advance-or-in-arrears "Direct link to heading")
With Lago, you can define if the base charge of the Plan is paid **in advance**
or **in arrears**.
* If the toggle is `off` (boolean set to FALSE), the Plan is paid for the past
period (in arrears).
* If the toggle is `on` (boolean set to TRUE), the Plan is paid upfront (in
advance) for the period.
Note that this toggle only affects the base amount of the Plan. Additional
charges for per-usage Billable metrics **are always paid in arrears because
they are linked to a past consumption of your customers.**
## The trial period (optional)[](#the-trial-period-optional "Direct link to heading")
You can decide to apply a `Trial period` for a Plan. This means your customers
can test the Plan without being charged for a certain number of days. This is
optional and if the value is null, the Plan holds 0 day of trial.
Note that the trial period **can only be specified in days**. A pro-rata is
applied to the Plan regarding the number of days offered.
A trial period can only be applied to the first subscribed Plan. In case of an
upgrade or downgrade, the trial period of the new Plan **is not applied**.
The trial period is only applied to the subscription fee.
Any events received during the trial period will be taken into account at the end
of the billing cycle. Pay-in-advance charges will be invoiced and collected immediately
after an event is received.
If you want maximum flexibility, you can define two different Plans: one for the
free trial and one regular plan. A new customer starts on the free plan, and you
can configure the regular plan to start after the trial period. The free plan
subscription will automatically be terminated when the regular plan starts.
## Taxes applied on plans or charges
You have the option to store taxes either at a Plan level or for specific charges.
This choice entails that whenever you apply this plan to a customer without taxes,
invoice fees will inherit the taxes defined in the corresponding plan.
It's important to acknowledge that taxes applied to a plan will influence the charges,
unless the taxes are explicitly defined for the individual charge.
## Pro-ratas based on subscription date[](#pro-ratas-based-on-subscription-date "Direct link to heading")
Obviously, we know that your customers don't necessarily sign up for a Plan at
the very begining of each month (or each year). This is why Lago automatically
applies a pro-rata for the first and the last subscription period of a Plan.
Here is an example: A `Customer X` signs up for the Plan `Start` (base amount of
10€, with no trial period) on April 15, 2022.
* If the Plan is defined to be `paid in arrears`, this Customer will be charged
5€ for the first month at the end of the period (May 1, 2022).
* If the Plan is defined to be `paid in advance`, this Customer is charged 5€
straight away for the first month (April 15, 2022).
Note that pro-ratas can also be applied in case of **upgrades or downgrades**.
# Progressive billing
Progressive billing, also known as threshold billing, automatically triggers an invoice when a customer's cumulative usage reaches predefined thresholds. This method ensures that customers cannot exceed certain usage limits without ensuring payment is received, reducing the risk of unpaid services or fraud.
**PREMIUM ADD-ON** ✨
This progressive billing feature is available upon request only. Please **[contact us](mailto:hello@getlago.com)** to get access to this premium feature.
## Lifetime usage
In the context of progressive billing, thresholds and invoicing behavior are **determined by the lifetime usage of a subscription**.
This approach means that Lago continuously tracks and aggregates **the total usage across all billing periods**.
By considering this cumulative usage, Lago can accurately assess whether a customer has reached predefined thresholds.
When the lifime usage reaches a specific threshold, Lago automatically triggers the invoicing process, ensuring that usage is invoiced promptly before it exceeds the specified limits. This mechanism helps prevent overuse of services without corresponding invoice and payment, offering a safeguard against potential revenue leakage.
It's important to note that lifetime usage is persistent across periods, meaning that even if a customer's usage fluctuates, Lago will account for the entire history to determine if and when an invoice should be issued.
The lifetime usage is calculated based on the usage amount before taxes.
## Setting up thresholds
For the progressive billing feature, you can configure two types of thresholds: Step-Based Thresholds and Recurring Thresholds.
### Step-based thresholds
For Step-Based Thresholds, invoices are generated when the lifetime usage of a subscription reaches a defined threshold.
You can set an unlimited number of thresholds, each with a specific amount and a unique name.
To add progressive billing Step-Based Thresholds from the UI:
1. Navigate to the desired plan;
2. Access the Advanced Settings;
3. Locate the Progressive Billing section; and
4. Add your thresholds.
```json Add progressive billing thresholds {14-27}
{
"plan": {
"name": "Premium",
"invoice_display_name": null,
"created_at": "2024-08-26T14:23:53Z",
"code": "premium",
"interval": "monthly",
"description": "",
"amount_cents": 10000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"charges": [...],
"usage_thresholds": [
{
"amount_cents": 500,
"threshold_display_name": "Step 1 "
},
{
"amount_cents": 5000,
"threshold_display_name": "Step 2"
},
{
"amount_cents": 10000,
"threshold_display_name": "Step 3"
}
]
}
}
```
In the above example, Lago will issue an invoice when the specified threshold is met:
* `Invoice #1`: When the lifetime usage reaches \$5;
* `Invoice #2`: When the lifetime usage reaches \$20;
* `Invoice #3`: When the lifetime usage reaches \$50;
* `Invoice #4`: When the lifetime usage reaches \$100;
* `Invoice #5`: When the lifetime usage reaches \$1,000;
* Then, resume to 'end of the month' billing.
### Recurring threshold
In addition to Step-Based Thresholds, you can also set up a Recurring Threshold. This threshold determines what happens after the final step-based threshold is reached.
If a recurring threshold is defined, Lago will continue to issue invoices each time the lifetime usage increases by the specified amount.
For example, as shown in the image below, after the last threshold, Lago will automatically bill \$100 each time the lifetime usage increments by that amount.
To add a recurring threshold from the UI:
1. Navigate to the desired plan;
2. Access the Advanced Settings;
3. Locate the Progressive Billing section;
4. Toggle the 'Recurring' switch; and
5. Enter a name and define the recurring threshold amount.
```json Add a recurring billing threshold
{
"plan": {
"name": "Premium",
"invoice_display_name": null,
"created_at": "2024-08-26T14:23:53Z",
"code": "premium",
"interval": "monthly",
"description": "",
"amount_cents": 10000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"charges": [...],
"usage_thresholds": [
{
"amount_cents": 500,
"threshold_display_name": "Step 1 "
},
{
"amount_cents": 5000,
"threshold_display_name": "Step 2"
},
{
"amount_cents": 10000,
"threshold_display_name": "Step 3"
},
{
"amount_cents": 5000,
"threshold_display_name": "Bill every 50 dollars",
"recurring": true
}
]
}
}
```
## Invoicing behaviors
For our progressive billing feature, invoices are generated whenever a threshold is crossed, regardless of when it occurs within a billing period.
However, there are a few specific behaviors and edge cases related to this feature that are important to consider.
### Invoicing during job execution
It's important to note that **threshold billing occurs when our progressive billing job runs** (every 5 minutes by default, though this interval can be adjusted on a case-by-case basis).
This means that Lago does not trigger the invoice immediately when the threshold is crossed but rather at a predefined interval.
As a result, Lago will invoice the total usage at the time the job runs, **which may slightly exceed the threshold**.
For instance, if your billing threshold is \$10 but the job runs when the customer's current usage is \$12, Lago will invoice for the full \$12.
### Charges included in the calculation
**Only charges billed in arrears (recurring or metered) are included in the lifetime usage calculation for progressive billing invoices**.
This means any charges paid in advance are excluded from this progressive billing feature.
### Excluding already billed usage
When a customer crosses a threshold for a specific subscription, Lago will invoice the total usage for the current period,
ensuring that any 'previously billed usage' is excluded.
This approach provides customers with a clear view of their current consumption while preventing them from being charged again
for usage already invoiced under previous thresholds.
It's important to note that the invoice template (as shown below) includes the following details:
* The total usage for the current period;
* An adjustment that excludes previously billed usage; and
* A footer that provides context, explaining the reason for the invoice, including lifetime usage and the threshold that was crossed.
### Grace period edge cases
It's important to note that **progressive billing invoices are not subject to a grace period** and, therefore, cannot be in a `draft` status.
The reason for this is that draft invoices are not `finalized`, and progressive billing calculations are based solely on `finalized` invoices. Including draft invoices in these calculations would significantly alter the accuracy of the progressive billing process.
### Applying discounts
Progressive billing invoices will automatically apply any available discounts, including coupons, prepaid credits, or credit notes.
### Overriding subscription thresholds
To provide maximum flexibility with the progressive billing feature, you can **override the default plan's thresholds for a specific subscription**.
This allows a particular subscription to have its own customized thresholds. You can add or remove thresholds as needed, or even disable the progressive billing feature entirely for a specific subscription.
### Modifying thresholds
You can edit, add, or remove progressive billing thresholds—or even disable this feature—at any time for a plan or subscription.
This flexibility allows you to adjust thresholds to meet your customer's needs without needing to rebuild everything from scratch.
### Being notified
Since progressive billing invoices can be triggered at any time during a billing period, it's crucial to stay informed when a customer crosses a threshold.
Lago sends a [webhook notification](/api-reference/webhooks/messages#subscription-usage-threshold-reached), `subscription.usage_threshold_reached`, providing details about the subscription and the specific threshold that was exceeded.
# RBAC - Role Base Access Control
Define user roles & permissions in Lago.
## Admin role
Admins wield full control over Lago, managing billable metrics, plans, customers, subscriptions, settings or financial analysis.
Typically, developers with admin roles handle all critical billing operations. By default, the account creator is assigned the Admin role.
Only admins can invite new members and assign roles. Your account must always
have at least one admin.
## Account manager role
The Account manager role suits Sales or Customer Success Managers, enabling them to carry out billing tasks for customers.
Account Managers can assign subscriptions, coupons, add-ons, and override prices but are not permitted to modify metrics or plans.
## Finance & analyst role
The Finance & analyst role is view-only, restricted from creating or editing metrics and plans, or assigning core billing actions such as coupons,
subscriptions. It's ideal for analyzing financial data, reviewing invoices, and issuing credit notes as necessary.
## Roles and permissions
| category | name | description | admin | manager | finance |
| ----------------- | --------------------- | ----------------------------------------------- | ----- | ------- | ------- |
| Analytics | view | Access the Analytics Section | ✅ | ❌ | ✅ |
| Billable Metrics | view | Access Billable Metrics Section | ✅ | ❌ | ❌ |
| Billable Metrics | create | Create a Billable Metric | ✅ | ❌ | ❌ |
| Billable Metrics | update | Update a Billable Metric | ✅ | ❌ | ❌ |
| Billable Metrics | delete | Delete a Billable Metric | ✅ | ❌ | ❌ |
| Plans | view | Access Plans Section | ✅ | ✅ | ✅ |
| Plans | create | Create a New Plan | ✅ | ❌ | ❌ |
| Plans | update | Update a Plan | ✅ | ❌ | ❌ |
| Plans | delete | Delete a Plan | ✅ | ❌ | ❌ |
| Plans | create | Duplicate a Plan | ✅ | ❌ | ❌ |
| Addons | view | Access Add-ons Section | ✅ | ✅ | ✅ |
| Addons | create | Create a New Add-on | ✅ | ❌ | ❌ |
| Addons | update | Update an Add-on | ✅ | ❌ | ❌ |
| Addons | delete | Delete an Add-on | ✅ | ❌ | ❌ |
| Coupons | view | Access Coupons Section | ✅ | ✅ | ✅ |
| Coupons | create | Create a New Coupon | ✅ | ❌ | ❌ |
| Coupons | update | Update a Coupon | ✅ | ❌ | ❌ |
| Coupons | delete | Delete a Coupon | ✅ | ❌ | ❌ |
| Coupons | update | Terminate a Coupon | ✅ | ❌ | ❌ |
| Coupons | attach | Apply a Coupon | ✅ | ✅ | ❌ |
| Coupons | detach | Remove a Coupon | ✅ | ✅ | ❌ |
| Customers | view | Access Customers Section | ✅ | ✅ | ✅ |
| Customers | view | Access Customers Details | ✅ | ✅ | ✅ |
| Customers | create | Create a New Customer | ✅ | ✅ | ❌ |
| Customers | update | Update a Customer | ✅ | ✅ | ❌ |
| Customers | delete | Delete a Customer | ✅ | ✅ | ❌ |
| Subscriptions | view | Access subscriptions | ✅ | ✅ | ✅ |
| Subscriptions | create | Assign a New Plan | ✅ | ✅ | ❌ |
| Subscriptions | update | Edit subscription | ✅ | ✅ | ❌ |
| Subscriptions | update | Upgrade/downgrade | ✅ | ✅ | ❌ |
| Subscriptions | delete | Delete subscription | ✅ | ✅ | ❌ |
| Wallets | create | Create a Wallet | ✅ | ✅ | ❌ |
| Wallets | update | Edit a Wallet | ✅ | ✅ | ❌ |
| Wallets | top\_up | Top-up a Wallet | ✅ | ✅ | ❌ |
| Wallets | terminate | Terminate a Wallet | ✅ | ✅ | ❌ |
| Invoices | view | Access Invoice List | ✅ | ✅ | ✅ |
| Invoices | view | Download an Invoice | ✅ | ✅ | ✅ |
| Invoices | send | Resend an Invoice | ✅ | ✅ | ✅ |
| Invoices | update | Update Payment Status | ✅ | ✅ | ✅ |
| Invoices | void | Void an Invoice | ✅ | ✅ | ✅ |
| Invoices | create | One-off Invoices | ✅ | ✅ | ✅ |
| Invoices | update | Edit a Draft Invoice | ✅ | ✅ | ✅ |
| Invoices | update | Refresh a Draft invoice | ✅ | ✅ | ✅ |
| Invoices | update | Finalize a Draft invoice | ✅ | ✅ | ✅ |
| Draft Invoices | update | Edit a Draft Invoice | ✅ | ✅ | ✅ |
| Draft Invoices | update | Refresh a Draft invoice | ✅ | ✅ | ✅ |
| Draft Invoices | update | Finalize a Draft invoice | ✅ | ✅ | ✅ |
| Credit Notes | view | Access Credit Notes List | ✅ | ✅ | ✅ |
| Credit Notes | create | Create a Credit Note | ✅ | ✅ | ✅ |
| Credit Notes | view | Download a Credit Note PDF | ✅ | ✅ | ✅ |
| Credit Notes | update | Don't know what this is but there is a mutation | ✅ | ✅ | ✅ |
| Credit Notes | void | Void a Credit Note | ✅ | ✅ | ✅ |
| Customer Settings | view | Access Customer’s Settings | ✅ | ✅ | ✅ |
| Customer Settings | update:tax\_rates | Add Tax Rates | ✅ | ✅ | ✅ |
| Customer Settings | update:payment\_terms | Edit Net Payment Terms | ✅ | ✅ | ✅ |
| Customer Settings | update:grace\_period | Edit Grace Period | ✅ | ✅ | ✅ |
| Customer Settings | update:lang | Edit Document Language | ✅ | ✅ | ✅ |
| Developers | manage | Access Developers Section | ✅ | ❌ | ❌ |
| Developers | keys:manage | Access API Keys | ✅ | ❌ | ❌ |
| Developers | manage | Access Events List | ✅ | ❌ | ❌ |
| Developers | manage | Access Webhooks | ✅ | ❌ | ❌ |
| Organization | view | Access Organization Settings | ✅ | ❌ | ✅ |
| Organization | update | Edit Organization Information | ✅ | ❌ | ✅ |
| Organization | invoices:view | Access Invoices’ Global Information | ✅ | ❌ | ✅ |
| Organization | invoices:update | Edit Invoices’ Global Information | ✅ | ❌ | ✅ |
| Organization | taxes:view | Access Global Taxes Information | ✅ | ❌ | ❌ |
| Organization | taxes:update | Edit Global Taxes Information | ✅ | ❌ | ❌ |
| Organization | emails:view | Access Emails Settings | ✅ | ❌ | ❌ |
| Organization | emails:update | Edit Emails Settings | ✅ | ❌ | ❌ |
| Organization | integrations:view | Access Integrations Section | ✅ | ❌ | ✅ |
| Organization | integrations:create | Add an Integration | ✅ | ❌ | ✅ |
| Organization | integrations:update | Edit an Integration | ✅ | ❌ | ✅ |
| Organization | integrations:delete | Delete an Integration | ✅ | ❌ | ✅ |
| Organization | members:view | Access Members Section | ✅ | ❌ | ❌ |
| Organization | members:create | Add a Member and Choose Its Role | ✅ | ❌ | ❌ |
| Organization | members:update | Edit a Member and Its Role | ✅ | ❌ | ❌ |
| Organization | members:delete | Delete a Member | ✅ | ❌ | ❌ |
# SOC 2 Type 2
Keeping your data secure.
Lago has achieved SOC 2 Type 2 compliance for its fully hosted version, which certifies the effectiveness of our operating and security controls.
Please contact [hello@getlago.com](mailto:hello@getlago.com) to request the full report. Please note that the self-hosted version is compliant by default, as you own the data and the infrastructure.
## Data Security
Lago encrypts data at rest and in transit for all of our customers. We use Amazon Web Service’s Key Management System (KMS) to manage encryption keys for maximum security, in line with industry best practices.
## Application Security
Lago also uses Dependabot, a high-quality analysis tooling provided by GitHub Advanced Security, to secure our product at every step of the development process.
## Infrastructure Security
Lago uses Amazon Web Services to host our application. We make use of the security products embedded within the AWS ecosystem, including KMS and GuardDuty.
In addition, we deploy our application using Kubernetes containers run on AWS managed services, meaning we typically do not manage servers or EC2 instances in production.
If you have further questions about security, please refer to [this page](https://www.getlago.com/company/security)
# Single Sign-On (SSO)
## Google SSO
Lago integrates with Google Single Sign-On (Google SSO), enabling your team to access Lago using their existing Google credentials.
This seamless integration allows team members to log in with their corporate Gmail accounts, eliminating the need for additional usernames and passwords.
This streamlines the login process and enhances security by leveraging Google's authentication infrastructure.
## Okta SSO
**PREMIUM ADD-ON** ✨
This add-on is available on demand only. Please **[contact us](mailto:hello@getlago.com)** to get access to this premium add-on.
Lago integrates with Okta Single Sign-On (Okta SSO), enabling your team to access Lago using their existing Okta credentials.
### Connect Lago to Okta
To connect Lago to Okta, please follow these steps:
1. Go to your Lago Settings view.
2. Access the Authentication section.
3. Configure Okta by adding the requested information:
4. Domain name | Okta public key | Okta private key | Okta organization name
### Log in to Lago or join an existing organization
Once this integration is switched on, it allows team members to log in or join an existing organization with their corporate Okta accounts, eliminating the need for additional usernames and passwords. This streamlines the login process and enhances security by leveraging Okta’s authentication infrastructure.
### Edit or delete Okta's connection
Once this integration is switched on, you can edit the connection information or delete it. Please note that once deleted, you won't be able to access Lago via Okta SSO. Use the Forgot password feature to regain access to your account.
# Useful commands
Useful commands for self-hosted users.
Below is a compilation of essential commands tailored for open-source enthusiasts, primarily designed for managing invoicing tasks,
whether for immediate processing or scheduling.
These commands are designed to execute a Rails console (rails c) within a Docker container named api, which is managed by Docker Compose.
```
docker-compose exec api rails c
```
## Dry-run invoice in the future
Use this to simulate a dry run invoice for a future date. Ensure to specify the correct subscription `external_id` and the targeted invoice issuance date.
```ruby
# In the rails Console
subscription = Subscription.find_by(external_id: 'YOUR_SUB_EXTERNAL_ID')
date = DateTime.parse('2024-10-01').to_i
BillSubscriptionJob.perform_later([subscription], date)
```
## Issue invoice immediately
Use this to issue an invoice immmediately. Ensure to specify the correct subscription `external_id` and the current date.
```ruby
# In the rails Console
subscription = Subscription.find_by(external_id: 'YOUR_SUB_EXTERNAL_ID')
timestamp = DateTime.parse('2024-04-01').to_i
BillSubscriptionJob.perform_now([subscription], timestamp, invoicing_reason: :subscription_periodic)
```
## Remove cache for a subscription
Use this to remove the cache on a specific subscription.
```ruby
# In the rails Console
Subscriptions::ChargeCacheService.expire_for_subscription(Subscription.find('YOUR_SUB_EXTERNAL_ID'))
```
To remove the cache for all subscriptions, you can alternatively use this command:
```ruby
# In the rails Console
Subscription.find_each {|s| Subscriptions::ChargeCacheService.expire_for_subscription(s) }
```
# Docker
Docker is the easiest way to get started with the self-hosted version of Lago.
## Requirements[](#requirements "Direct link to heading")
1. Install [Docker](https://docs.docker.com/get-docker/) on your machine;
2. Make sure [Docker Compose](https://docs.docker.com/compose/install/) is
installed and available (it should be the case if you have chosen to install
Docker via Docker Desktop); and
3. Make sure
[Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) is
installed on your machine.
## Run the app[](#run-the-app "Direct link to heading")
To start using Lago, run the following commands in a shell:
```shell
# Get the code
git clone https://github.com/getlago/lago.git
# Go to Lago folder
cd lago
# Set up environment configuration
echo "LAGO_RSA_PRIVATE_KEY=\"`openssl genrsa 2048 | base64`\"" >> .env
source .env
# Start the api
docker compose up -d api
# Create the database
docker compose exec api rails db:create
docker compose exec api rails db:migrate
# Start all other components
docker compose up
```
You can now open your browser and go to [http://localhost](http://localhost) to
connect to the application. Just after
[signing up](#signing-up), Lago's API is exposed
at [http://localhost:3000](http://localhost:3000).
## Signing up[](#signing-up "Direct link to heading")
It's mandatory to create your organization by signing up to Lago. This
organization is the core object of your biller as it's used to invoice your
customers.
1. Write down your `organization name`;
2. Use the main billing `email` of your company; and
3. Define the admin `password` for this email.
You will be able to **invite other email addresses within the application**. If
you already have an account, you can also log in. Once you are able to access
the app, you can retrieve your API key.
## Find your API Key[](#find-your-api-key "Direct link to heading")
Your API Key can be found directly in the UI:
1. Access the **Developer** section from the sidebar;
2. The first tab of this section is related to your **API keys**; and
3. Click the **Copy** button to copy it to clipboard.
## Configuration[](#configuration "Direct link to heading")
### Version[](#version "Direct link to heading")
Docker images are always updated to the last stable version in the
`docker-compose.yml` file. You can use a different tag if needed by checking the
[releases list](https://github.com/getlago/lago/releases).
We recommend to avoid the usage of `latest` tag, you should use the last
tagged version, you can track what are the last version on Dockerhub
* lago-api :
[https://hub.docker.com/repository/docker/getlago/api](https://hub.docker.com/repository/docker/getlago/api)
* lago-front :
[https://hub.docker.com/repository/docker/getlago/front](https://hub.docker.com/repository/docker/getlago/front)
### Environment variables[](#environment-variables "Direct link to heading")
Lago uses the following environment variables to configure the components of the
application. You can override them to customise your setup.
| Variable | Default value | Description |
| ------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POSTGRES_HOST` | db | (*With Docker compose*) Host name of the postgres server |
| `POSTGRES_DB` | lago | (*With Docker compose*) Name of the postgres database |
| `POSTGRES_USER` | lago | (*With Docker compose*) Database user for postgres connection |
| `POSTGRES_PASSWORD` | changeme | (*With Docker compose*) Database password for postgres connection |
| `POSTGRES_PORT` | 5432 | (*With Docker compose*) Port the postgres database listens to |
| `POSTGRES_SCHEMA` | public | Name of the postgres schema |
| `DATABASE_URL` | | (*Without docker compose*) Full url to the postgres server |
| `DATABASE_POOL` | 10 | Max number of connection opened to the postgres database per api, worker and clock instances |
| `DATABASE_PREPARED_STATEMENTS` | true | Enable or disable prepared statements in the postgres database |
| `REDIS_HOST` | redis | Host name of the redis server |
| `REDIS_PORT` | 6379 | Port the redis database listens to |
| `REDIS_PASSWORD` | | Password of the redis server |
| `LAGO_REDIS_CACHE_HOST` | redis | Host name of the redis cache server |
| `LAGO_REDIS_CACHE_PORT` | 6379 | Port the redis cache server listens to |
| `LAGO_REDIS_CACHE_PASSWORD` | | Password of the redis cache server |
| `LAGO_REDIS_CACHE_POOL_SIZE` | 5 | Max number of connections in the redis cache connection pool |
| `LAGO_MEMCACHE_SERVERS` | | Coma separated list of memcache servers |
| `LAGO_FRONT_URL` | [http://localhost](http://localhost) | URL of the Lago front-end application.Used for CORS configuration |
| `FRONT_PORT` | 80 | Port the front-end application listens to |
| `LAGO_API_URL` | [http://localhost:3000](http://localhost:3000) | URL of the Lago back-end application |
| `API_URL` | [http://localhost:3000](http://localhost:3000) | URL of the Lago back-end application defined for the front image |
| `API_PORT` | 3000 | Port the back-end application listens to |
| `SECRET_KEY_BASE` | your-secret-key-base-hex-64 | Secret key used for session encryption |
| `SENTRY_DSN` | | Sentry DSN key for error and performance tracking on Lago back-end |
| `SENTRY_DSN_FRONT` | | Sentry DSN key for error and performance tracking on Lago front-end |
| `LAGO_RSA_PRIVATE_KEY` | | Private key used for webhook signatures |
| `LAGO_SIDEKIQ_WEB` | | Activate the Sidekiq web UI, disabled by default |
| `LAGO_ENCRYPTION_PRIMARY_KEY` | your-encryption-primary-key | Encryption primary key used to secure sensitive values stored in the database |
| `LAGO_ENCRYPTION_DETERMINISTIC_KEY` | your-encryption-deterministic-key | Encryption deterministic key used to secure sensitive values stored in the database |
| `LAGO_ENCRYPTION_KEY_DERIVATION_SALT` | your-encryption-derivation-salt | Encryption key salt used to secure sensitive values stored in the database |
| `LAGO_WEBHOOK_ATTEMPTS` | 3 | Number of failed attempt before stopping to deliver a webhook |
| `LAGO_USE_AWS_S3` | false | Use AWS S3 for files storage |
| `LAGO_AWS_S3_ACCESS_KEY_ID` | azerty123456 | AWS Access Key id that has access to S3 |
| `LAGO_AWS_S3_SECRET_ACCESS_KEY` | azerty123456 | AWS Secret Access Key that has access to S3 |
| `LAGO_AWS_S3_REGION` | us-east-1 | AWS S3 Region |
| `LAGO_AWS_S3_BUCKET` | bucket | AWS S3 Bucket name |
| `LAGO_AWS_S3_ENDPOINT` | | S3 compatible storage endpoint. Should be set only if you are using another storage provider than AWS S3 |
| `LAGO_USE_GCS` | false | Use Google Cloud Service Cloud Storage for file storage, ⚠️ If you want to use GCS, you have to pass the credentials json key file to the api and worker service |
| `LAGO_GCS_PROJECT` | | GCS Project name |
| `LAGO_GCS_BUCKET` | | GCS Bucket Name |
| `LAGO_PDF_URL` | [http://pdf:3000](http://pdf:3000) | PDF Service URL on your infrastructure |
| `LAGO_DISABLE_SIGNUP` | | Disable Sign up when running Lago in self-hosted |
| `LAGO_RAILS_STDOUT` | true | Set to true to activate logs on containers |
| `LAGO_DISABLE_WALLET_REFRESH` | | Disable automatic refresh of wallet ongoing balance |
| `GOOGLE_AUTH_CLIENT_ID` | | Client ID for Google auth Single Sign On |
| `GOOGLE_AUTH_CLIENT_SECRET` | | Client Secret for Google auth Single Sign On |
We recommend that you change `POSTGRES_PASSWORD`, `SECRET_KEY_BASE`,
`LAGO_RSA_PRIVATE_KEY`, `LAGO_ENCRYPTION_PRIMARY_KEY`,
`LAGO_ENCRYPTION_DETERMINISTIC_KEY` and `LAGO_ENCRYPTION_KEY_DERIVATION_SALT` to
improve the security of your Lago instance:
* `SECRET_KEY_BASE` can be generated using the `openssl rand -hex 64` command.
* `LAGO_RSA_PRIVATE_KEY` can be generated using the
`openssl genrsa 2048 | base64` command.
* `LAGO_ENCRYPTION_PRIMARY_KEY`, `LAGO_ENCRYPTION_DETERMINISTIC_KEY` and
`LAGO_ENCRYPTION_KEY_DERIVATION_SALT` can all be gerated using the
`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1` command.
### Components[](#components "Direct link to heading")
Lago uses the following containers:
| Container | Role |
| ------------ | --------------------------------------------------------------------- |
| `front` | Front-end application |
| `api` | API back-end application |
| `api_worker` | Asynchronous worker for the API application |
| `api_clock` | Clock worker for the API application |
| `db` | Postgres database engine used to store application data |
| `redis` | Redis database engine used as a queuing system for asynchronous tasks |
| `pdf` | PDF generation powered by Gotenberg |
You can also use your own database or Redis server. To do so, remove the `db`
and `redis` configurations from the `docker-compose.yml` file and update the
environment variables accordingly.
### SSL Support[](#ssl-support "Direct link to heading")
Lago Front application can be configured to support SSL certificates. You have
two options to achieve this:
* by using a self-signed certificate
* by using a signed certificate generated by Let's Encrypt
#### Self Signed Certificate[](#self-signed-certificate "Direct link to heading")
* Run the script to generate the certificates
```shell
# Be sure to be in your lago folder
./extra/init-selfsigned.sh
# This should create certificates in the ./extra/ssl/ folder
```
* Take a look at the `docker-compose.yml` file and uncomment the part related to
the Self-Signed certificate
```yaml
volumes:
- ./extra/nginx-selfsigned.conf:/etc/nginx/conf.d/default.conf
- ./extra/ssl/nginx-selfsigned.crt:/etc/ssl/certs/nginx-selfsigned.crt
- ./extra/ssl/nginx-selfsigned.key:/etc/ssl/private/nginx-selfsigned.key
- ./extra/ssl/dhparam.pem:/etc/ssl/certs/dhparam.pem
```
* You can now start the front application with a self signed SSL certificate
support
```shell
docker-compose up front
```
#### Let's Encrypt Certificate[](#lets-encrypt-certificate "Direct link to heading")
* Edit the file `extra/init-letsencrypt.sh`
* You must replace `lago.example` with your domain name
* You must enter a valid email address
* Edit the file `extra/nginx-letsencrypt.conf`
* You must replace `lago.example` with your domain name
* Uncomment the [Cerbot lines](https://github.com/getlago/lago/blob/5d08b61f4f174f445b258005854aaa18ca049266/docker-compose.yml#L124-L129) in the `docker-compose.yml` file
* Run the following script
```shell
# Be sure to be in your lago folder
./extra/init-letsencrypt.sh
# You will be asked to provide some information
# After that you should be able to see the extra/certbot folder
```
* Take a look at the `docker-compose.yml` file and uncomment all the parts
related to the Let's Encrypt's support
```yaml
command:
'/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx
-g "daemon off;"'''
---
volumes:
- ./extra/nginx-letsencrypt.conf:/etc/nginx/conf.d/default.conf
- ./extra/certbot/conf:/etc/letsencrypt
- ./extra/certbot/www:/var/www/certbot
```
* You can now start the front application with the signed certificate support
```shell
docker-compose up front
```
### Storage[](#storage "Direct link to heading")
By default, Lago uses the internal storage of the container. You can customize
it by defining different environment variables.
We currently support :
* AWS S3
* AWS S3 Compatibles Endpoints
* Google Cloud Service Cloud Storage
If you use S3 compatibles endpoints, you should set the `LAGO_AWS_S3_REGION`
to a default value (ei: `us-east-1`), it is required to work properly!
#### AWS S3[](#aws-s3 "Direct link to heading")
You have to set these variables to use AWS S3.
| Name | Description |
| ------------------------------- | --------------------------------------- |
| `LAGO_USE_AWS_S3` | Set to "true" if you want to use AWS S3 |
| `LAGO_AWS_S3_ACCESS_KEY_ID` | AWS S3 Credentials Access Key Id |
| `LAGO_AWS_S3_SECRET_ACCESS_KEY` | AWS S3 Credentials Secret Access Key |
| `LAGO_AWS_S3_REGION` | AWS S3 Region |
| `LAGO_AWS_S3_BUCKET` | AWS S3 Bucket |
#### AWS S3 Compatible Endpoints[](#aws-s3-compatible-endpoints "Direct link to heading")
You have to set these variables to use AWS S3 Compatible Endpoints.
| Name | Description |
| ------------------------------- | ------------------------------------------------------------ |
| `LAGO_USE_AWS_S3` | Set to "true" if you want to use AWS S3 Compatible Endpoints |
| `LAGO_AWS_S3_ENDPOINT` | AWS S3 Compatible Endpoint |
| `LAGO_AWS_S3_ACCESS_KEY_ID` | AWS S3 Credentials Access Key Id |
| `LAGO_AWS_S3_SECRET_ACCESS_KEY` | AWS S3 Credentials Secret Access Key |
| `LAGO_AWS_S3_BUCKET` | AWS S3 Bucket |
| `LAGO_AWS_S3_REGION` | Not used but required by the AWS SDK |
#### Google Cloud Service Cloud Storage[](#google-cloud-service-cloud-storage "Direct link to heading")
You have to set those variables to use GCS Cloud Storage.
| Name | Description |
| ------------------ | -------------------------------------------------- |
| `LAGO_USE_GCS` | Set to "true" if you want to use GCS Cloud Storage |
| `LAGO_GCS_PROJECT` | GCS Project name |
| `LAGO_GCS_BUCKET` | GCS Bucket name |
In the `docker-compose.yml` file, you must uncomment the lines and pass the
correct GCS credentials json file.
```yaml
api:
volumes:
- gcs_keyfile.json:/app/gcs_keyfile.json
api-worker:
volumes:
- gcs_keyfile.json:/app/gcs_keyfile.json
```
### SMTP Configuration[](#smtp-configuration")
In order to use the email feature, you need to configure some environment variables.
In addition to this configuration, defining an organization email in Settings > Organization is mandatory; without it, emails will not be sent.
| Name | Description |
| -------------------- | -------------------------------------------------------------------------------- |
| `LAGO_FROM_EMAIL` | Required to send emails (i.e: [noreply@getlago.com](mailto:noreply@getlago.com)) |
| `LAGO_SMTP_ADDRESS` | Address of the SMTP server |
| `LAGO_SMTP_PORT` | Port of the SMTP Server |
| `LAGO_SMTP_USERNAME` | Username of the SMTP Server |
| `LAGO_SMTP_PASSWORD` | Password of the SMTP Server |
#### Single Sign On using Google authentication[](#single-sign-on-using-google-authentication)
In order to enable Google authentication for single sign on, you have to set those variables.
| Name | Description |
| --------------------------- | -------------------------------------------- |
| `GOOGLE_AUTH_CLIENT_ID` | Client ID for Google auth Single Sign On |
| `GOOGLE_AUTH_CLIENT_SECRET` | Client Secret for Google auth Single Sign On |
# Overview
Deploy Lago seamlessly on your infrastructure, compatible with both free and premium editions.
Lago provides versatile hosting options: on your local computer, a dedicated server, or in the cloud.
## Officially Supported
Install Lago on your infrastructure with Docker Compose for easy deployment.
Utilize official Helm charts for deploying Lago on Kubernetes.
# Tracking & Analytics
## Why does Lago need data?[](#why-does-lago-need-data "Direct link to heading")
We decided to open-source the billing API we would have dreamt to use. As a
consequence of building a self hosted product, we are not able to easily collect
any usage metrics or insights to help us build a better product. This analytic
help us understand crucial behaviors and ship better quality to serve your
needs.
We decided to track, by default, so basic behaviors and metrics that are
important to understand the usage of Lago. We have built a minimum required
tracking plan to minimize the security impact of collecting those events. All
the metrics collected are listed in a further section. We make this as
transparent as possible, and we don't track financial information (amounts of
invoices, for instance).
The metrics are collected through the server side Ruby source from
[Segment.com](https://segment.com/docs/connections/sources/catalog/libraries/server/ruby/).
Lago will not collect any financial information about your customers or your
invoices.
## Opting out[](#opting-out "Direct link to heading")
As detailed previously, we ask you to keep as much as possible those tracked
metrics, unless you have a specific reason to opt out. Keeping the metrics
enabled is the easiest way for Lago to get feedback based on product usage.
In the case you need to remove it, we've created a very easy process to opt out.
In the environment variables, by passing the field `LAGO_DISABLE_SEGMENT` to
`true`, you prevent the entire tracking logic to run in your application.
## Detail of events collected by Lago[](#detail-of-events-collected-by-lago "Direct link to heading")
This event flow enables Lago to understand the full activation flow, from the
registration to the first invoice generated.
* `organization_registered`: when you create your organization by signing up to Lago
* `billable_metric_created`: whenever you create a new billable metric
* `plan_created`: whenever you create a new plan
* `customer_created`: whenever a customer is created in Lago
* `subscription_created`: when a subscription is assigned to a customer
* `coupon_created`: whenever a new coupon is created
* `applied_coupon_created`: when a coupon is assigned to a customer
* `add_on_created`: whenever a new add-on is created
* `invoice_created`: when a new invoice is emitted for a specific customer
* `payment_status_changed`: when the payment status of an invoice changes
* `credit_note_issued`: when a new credit note is issued for a customer
* `billable_metric_deleted`: when a billable metric is deleted
* `plan_deleted`: when a plan is deleted
* `customer_deleted`: when a customer account is deleted
## Detail of data collected about your organization[](#detail-of-data-collected-about-your-organization "Direct link to heading")
By default, we collect data of your organization that you used in the signup
form:
* Your organization's **email**; and
* Your organization's **name**.
By [opting out](#opting-out), your organization's data
won't be tracked anymore.
## Examples of collected payloads[](#examples-of-collected-payloads "Direct link to heading")
### billable\_metric\_created[](#billable%5Fmetric%5Fcreated "Direct link to heading")
```javascript
Analytics.track(
user_id: 'membership/f37a6b2e-1e79-4710-b0e2-9e451b532461',
event: 'billable_metric_created',
properties: {
aggregation_property: 'amount',
aggregation_type: 'sum_agg',
code: 'atm',
description: '',
hosting_type: 'self',
name: 'ATM',
organization_id: '7c868af7-201c-4ebc-9829-ca902e289e5f',
version: DateTime.iso8601('2022-07-27T00:00:00.000Z')
}
)
```
### customer\_created[](#customer%5Fcreated "Direct link to heading")
```javascript
Analytics.track(
user_id: 'membership/4ad5b91f-2a42-4a58-9786-6c07fa03a3d4',
event: 'customer_created',
properties: {
created_at: DateTime.iso8601('2022-08-10T09:34:37.479Z'),
customer_id: '29a17eed-021c-485e-b3fa-93d27db31c95',
hosting_type: 'cloud',
organization_id: '0d173830-9017-4f57-9d11-e3e83b3e38fe',
payment_provider: 'stripe',
version: DateTime.iso8601('2022-08-09T00:00:00.000Z')
}
)
```
### invoice\_created[](#invoice%5Fcreated "Direct link to heading")
```javascript
Analytics.track(
user_id: 'membership/f37a6b2e-1e79-4710-b0e2-9e451b532461',
event: 'invoice_created',
properties: {
hosting_type: 'cloud',
invoice_id: '0e31afd2-8e15-49e1-a6fb-11895fa03c97',
invoice_type: 'subscription',
organization_id: 'b3e35674-c3d1-4279-8ef1-271271b6cafb',
version: DateTime.iso8601('2022-07-27T00:00:00.000Z')
}
)
```
# Versions update
Lago's speed is rapidly increasing—remarkably fast. Billing updates occur frequently, precisely every 1 or 2 weeks. Over the course of a year, we've completed over 70 releases, culminating in approximately 30 comprehensive product updates. Maintaining the currency of your self-hosted instance is paramount for optimal billing engine functionality and alignment with the newest features. Below is a guide to achieve this seamlessly, all within the span of just 5 seconds.
## Why update your Lago self-hosted instance?
### Bug fixes and security enhancements
Updating your Lago open source instance serves a key purpose: resolving bugs and enhancing security protocols.
Just like any software, glitches may emerge, impacting operations and even jeopardizing security.
This is particularly vital in intricate tasks like metering, billing calculations, tax application, and managing financial statements.
By keeping up with updates, you guarantee your instance remains unaffected by recognized problems and vulnerabilities.
This proactive approach maintains a resilient and secure operational landscape for your company.
### Access to new features
Lago consistently evolves to meet the needs of its users. Each update introduces a host of new features aimed at enhancing the user
experience and expanding the capabilities of the platform. Some notable new features that updates might bring include core billing
enhancements, tax-related features, and additional settings options. By updating regularly, you can take advantage of these features and
streamline your workflows.
## Determining update frequency
The frequency of updates varies based on the development cycle of Lago. Generally, updates are released approximately once a week.
Keeping an eye on the [release notes](https://github.com/getlago/lago/releases) provided by the Lago team will give you insight into when updates are available and what changes they
entail. Regularly monitoring these release notes will allow you to stay informed and plan your updates accordingly. Billing updates occur
frequently, precisely every 1 or 2 weeks. Over the course of a year, we've completed over 70 releases, culminating in approximately
30 comprehensive [product updates](https://www.getlago.com/changelog).
## A seamless update process
Updating your Lago open source instance doesn't have to be a daunting task. With a clear procedure in place, you can ensure
a smooth transition to the latest version. Here's a step-by-step guide to help you navigate the update process:
### 1. Access your instance repository
Navigate to the repository where your Lago open source instance is stored. This is typically where you initially cloned or
downloaded the instance.
### 2. Pull the latest code
In the repository directory, execute the following command to pull the latest code from the remote repository:
```bash
git pull
```
This command fetches the most recent changes from the remote repository and merges them into your local instance.
### 3. Restart the updated instance
Once the code is up-to-date, navigate to the directory containing your Docker Compose file.
Execute the following command to start the updated instance:
```bash
docker compose up
```
This command will rebuild and launch your Lago instance with the latest changes.
### 4. Testing new features
After the instance restarts, you can now test our new features and give feedback to the team.
## Addressing concerns about breaking changes
It's natural to be cautious about updates, especially if you fear breaking changes that might disrupt your operations. However, the Lago team understands this concern and takes proactive measures to ensure a smooth update experience. By applying careful consideration to database and UI migrations, Lago mitigates the risk of breaking your application during updates. This thoughtful approach ensures that your workflows and user interfaces remain consistent even after applying the latest updates.
In conclusion, updating your Lago open source instance is a proactive step toward maintaining a secure and feature-rich environment for your operations. By staying current with bug fixes, security enhancements, and new features, you can harness the full potential of the platform. With a well-defined update process and the Lago team's commitment to stability, you can confidently keep your instance up-to-date, ensuring a seamless and productive experience.
# Assign a plan to a customer
A subscription is created when a plan is assigned to a customer. You can assign a plan to a customer at any time (i.e. when the customer record is created or later on).
To assign a plan to a customer through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab, click **"Add a plan"** on the right;
4. Select a plan (that you can overwrite if needed - [see below](#overwriting-a-plan));
5. Give a name to the subscription (name that will be displayed on the invoice - optional);
6. Give an id to the subscription (define your own subscription identifier - optional);
7. Set a subscription start date (start date of the subscription - [see below](#subscription-start-date));
8. Set a subscription end date (start date of the subscription - [see below](#subscription-end-date) - optional);
9. Choose whether the subscription should be renewed at the beginning of the period or on its anniversary date (see [below](#billing-cycles)); and
10. Click **"Add plan"** to confirm;
```bash Assign a plan to a customer
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "premium",
"external_id": "my_sub_12345789",
"name": "Repository 1",
"subscription_at": "2022-08-08T00:00:00Z",
"billing_time": "anniversary"
}
}'
```
When a subscription is active, Lago will automatically generate invoices for the customer according to the [plan model](/guide/plans/plan-model). It will also start monitoring the customer's consumption, which means that you can start pushing [events](/guide/events/ingesting-usage) related to this subscription.
The subscription date displayed in the app is based on the organization's timezone.
## Billing cycles
Optimize billing for your customers by assigning subscriptions based on either calendar dates or anniversary dates (the day they signed up).
By default, subscriptions are based on **calendar periods**. Therefore, if you assign a monthly plan to a customer on July 14th:
* The first invoice will be generated for the period July 14th to July 31st;
* The next invoice will be generated for the period August 1st to August 31st; and
* All future invoices will be generated for full calendar months.
When a subscription starts during the month, the subscription fee will be calculated on a **pro rata basis** according to the number of days.
Consider the following example:
> Your customer signs up for the Premium plan, \$50 monthly, on August 10th. There are 22 days left until the end of the month, including August 10th. Therefore, the subscription fee for August is:
> **22 days x \$50 / 31 days = \$35.48**
Another option is to use the **anniversary date** of the subscription to define a custom billing period.
For example:
> Your customer signs up for the Premium plan on August 10th.
> If you choose to align the billing cycle with the anniversary date of the subscription, the customer will be billed every 10th of the month.
> The first billing period will run from August 10th to September 9th.
## Subscription start date
By default, the subscription starts the day it is created. However, you can set a subscription date in the past or in the future.
The subscription date displayed in the app is based on the organization's timezone.
However, you can decide to start a subscription **in the past** or **in the future**.
If the start date of the subscription is in the past, the subscription is considered active.
Lago will not generate any invoices for past periods already completed.
The invoicing process varies depending on the [plan model](/guide/plans/plan-model) and [billing cycle](#billing-cycles):
* If the plan includes a subscription fee to be paid in advance, it will be considered as **already paid for the current period**. The next invoice will include the usage-based charges for the current period and the subscription fee for the next period (see example 1 below); and
* If the plan includes a subscription fee to be paid in arrears, it will be **included in the next invoice**, together with the usage-based charges for the current period (see example 2 below).
**Example 1:** Start date in the past and subscription fee to be paid in advance
**Example 2:** Start date in the past and subscription fee to be paid in arrears
If the start date of the subscription is in the future, the subscription is considered pending.
The invoicing process varies depending on the [plan model](/guide/plans/plan-model) and [billing cycle](#billing-cycles):
* If the plan includes a subscription fee to be paid in advance, when the subscription becomes active, Lago will automatically generate an **invoice for the subscription fee**. Usage-based charges will be included in the next invoice, generated at the end of the billing period (see example 3 below); and
* If the plan includes a subscription fee to be paid in arrears, when the subscription becomes active, **there will be no invoice**. The subscription fee and usage-based charges will be included in the invoice generated at the end of the billing period (see example 4 below).
**Example 3:** Start date in the future and subscription fee to be paid in advance
**Example 4:** Start date in the future and subscription fee to be paid in arrears
## Subscription end date
By default, if no subscription end date is specified, **the subscription will automatically renew at the end of the period**.
However, if you define an end date, the subscription will terminate on that date without renewal. This is valuable for contracts with specific termination dates.
Keep in mind, 45 days and 15 days before the subscription ends, a webhook alert, called `subscription.termination_alert`, will remind you. You then have two choices:
1. Allow the subscription to continue until the end date and finalize it; or
2. Adjust the subscription end date if the contract has been renegotiated.
Ensure that the subscription end date is set to a date later than the subscription start date.
Here is how you can define a susbcription end date from the UI:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab, click **"Add a plan"** on the right;
4. Set a subscription start date;
5. Set a subscription end date;
6. Choose between calendar or anniversary billing;
7. Click **"Add plan"** to confirm.
Use the `ending_at` field on the subscriptions endpoint.
```bash Define a subscription end date
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "premium",
"external_id": "my_sub_12345789",
"name": "Repository 1",
"subscription_at": "2022-08-08T00:00:00Z",
"ending_at": "2023-08-08T00:00:00Z",
"billing_time": "anniversary"
}
}'
```
## Multiple plans
You may create several subscriptions for a customer by assigning them multiple plans. This can be particularly useful if your application allows customers to create different projects or workspaces (e.g. Free plan for Workspace 1, Free plan for Workspace 2, Premium plan for Workspace 3, etc.).
There are some rules to keep in mind when assigning multiple plans to a customer:
1. All plans must be denominated in the same currency; and
2. You must specify the `external_subscription_id` for each event or create [batch events](/api-reference/events/batch).
We recommend that you give each subscription a name when assigning multiple plans to a customer. The subscription names will make it easier to differentiate each plan and will also be displayed on the invoices.
When multiple subscriptions are linked to a customer, Lago will automatically consolidate invoices when possible.
| | Month 1 | Month 2 | Month 3 | Month 4 | (...) | Month 13 |
| ---------------- | ------- | ------- | ------- | ------- | ----- | -------- |
| Plan A (monthly) | \$40 | \$40 | \$40 | \$40 | (...) | \$40 |
| Plan B (monthly) | \$60 | \$60 | \$60 | \$60 | (...) | \$60 |
| Plan C (yearly) | \$500 | - | - | - | (...) | \$500 |
| Total invoice | \$600 | \$100 | \$100 | \$100 | (...) | \$600 |
It is possible to link to the same customer subscriptions that are based on different billing cycles (e.g. a subscription based on calendar dates and another based on the anniversary date).
## Overriding a plan
**PREMIUM FEATURE** ✨
This feature is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
By assigning a subscription to a customer, you gain the flexibility to customize certain aspects of the initially selected plan.
This enables you to maintain a consistent plan structure for all customers while tailoring individualized discounts through price adjustments per customer.
To perform a plan overrides, assign a plan to a customer and you’ll be able to make modifications to the following elements:
1. Subscription invoice display name
2. Subscription fee
3. Plan currency
4. Plan trial period
5. Plan taxes
6. Charges properties (please note that the charge model cannot be modified)
7. Charge group definitions & properties (if applicable)
8. Charge minimum spending
9. Charge taxes
10. Charge invoice display name
11. [Progressive billing](/guide/plans/progressive-billing) thresholds
```bash Override a plan
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/subscriptions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "premium",
"external_id": "my_new_sub_123456789",
"name": "",
"subscription_at": "2022-08-08T00:00:00Z",
"ending_at": "2023-08-08T00:00:00Z",
"billing_time": "anniversary",
"plan_overrides": {
"name": "new_plan",
"invoice_display_name": "Subscription fee",
"description": "Overriden plan for customer X",
"amount_cents": 10000,
"amount_currency": "USD",
"trial_period": "0",
"tax_codes": [
"vat_10"
],
"charges": [
{
"id": "cac4cff7-e2d9-41e2-83e5-7947d91f0eb5",
"invoice_display_name": "Cards - custom price",
"billable_metric_code": "cards",
"min_amount_cents": 0,
"properties": {
"amount": "10"
},
"group_properties": [],
"taxes": []
}
]
}
}
}'
```
It's crucial to note that all overridden plans will remain associated with the initial plan but won't be visible in the plans list.
To access an overridden plan, simply click on the specific subscription item in the customer details view.
Moreover, all invoices generated from this subscription will be based from the overridden plan, not the initial plan.
Additionally, any coupons restricted to a plan code will apply to both the initial and overridden plans.
Importantly, any changes made to the initial plans will not impact the subscriptions linked to overridden plans.
## Deleting a plan
You could [delete a plan](/api-reference/plans/destroy) linked to existing subscriptions.
If you do so, the subscriptions associated with this plan will be immediately terminated. This action may trigger the generation of invoices and/or credit notes.
After deleting a plan, you can create a new one using the same code.
# Edit a subscription
You can edit a subscription at any time, whether it's active or pending.
Once a plan has been assigned to a customer, whether it's in a pending or active state, you can make edits to the subscription by following these steps:
1. Click on the three dots menu icon and select "Edit subscription."
2. Subscription Start and End Date\
You have the ability to modify the subscription start date if the subscription is pending, and if the chosen date is later than today. It's important to refer to the [guidelines for subscription start date](https://docs.getlago.com/guide/subscriptions/assign-plan#subscription-start-date) for further information.
3. Subscription End Date\
You can also make changes to the subscription end date, but it's important to refer to the [guidelines for subscription end date](https://docs.getlago.com/guide/subscriptions/assign-plan#subscription-end-date) for further information.
4. You can edit any prices listed for a subscription, including charges, commitments, tiers and spending minimums.
```bash Override a plan
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request PUT "$LAGO_URL/api/v1/subscriptions/{external_id}" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"subscription": {
"name": "",
"subscription_at": "2022-08-08T00:00:00Z",
"ending_at": "2023-08-08T00:00:00Z",
"plan_overrides": {
"name": "new_plan",
"invoice_display_name": "Subscription fee",
"description": "Overriden plan for customer X",
"charges": [
{
"id": "cac4cff7-e2d9-41e2-83e5-7947d91f0eb5",
"invoice_display_name": "Cards - custom price",
"properties": {
"amount": "10"
},
"group_properties": [],
}
]
}
}
}'
```
# Terminate a subscription
You can terminate a subscription at any time, whether it's active or pending.
## Terminate an active subscription
To terminate an active subscription through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab, select an active subscription; and
4. Click **"Terminate subscription"**; and to terminate an active subscription.
```bash Terminate an active subscription
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_ID="__YOUR_SUBSCRIPTION_ID__"
curl --location --request DELETE "$LAGO_URL/api/v1/subscriptions/$EXTERNAL_ID" \
--header "Authorization: Bearer $API_KEY"
```
When a subscription is terminated:
* Lago automatically generates an invoice for any outstanding usage-based charges that have not been invoiced yet;
* If the subscription fee for the plan has been paid in advance, Lago automatically issues a credit note for the unused number of days.
## Terminate a pending subscription
To terminate a pending subscription through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab, select a pending subscription (subscription set in the future or pending downgrade); and
4. Click **"Terminate subscription"**; and to cancel a pending subscription subscription.
```bash Terminate a pending subscription
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
EXTERNAL_ID="__YOUR_SUBSCRIPTION_ID__"
curl --location --request DELETE "$LAGO_URL/api/v1/subscriptions/$EXTERNAL_ID?status=pending" \
--header "Authorization: Bearer $API_KEY"
```
To ensure the termination of a pending subscription, it is crucial to include the `?status=pending` filter in your endpoint.
Neglecting to do so will render any termination attempts ineffective.
# Upgrades and downgrades
Customers have the flexibility to easily upgrade or downgrade their plan at any given moment.
To perform an upgrade or a downgrade through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. In the **"Overview"** tab. By clicking the ellipse icon, you can **"Upgrade/downgrade plan"**;
4. Give a name to the new subscription (name that will be displayed on the invoice - optional);
5. Provide a new subscription end date if needed (optional);
6. Click **"Upgrade/downgrade plan"** to confirm.
```bash Upgrade or downgrade a subscription
curl --request POST \
--url https://api.getlago.com/api/v1/subscriptions \
--header 'Bearer: ' \
--data '{
"subscription": {
"external_customer_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"plan_code": "new_plan",
"external_id": "existing_sub_id"
}
}'
```
## Upgrades behavior
An upgrade occurs when the subscription fee of the new plan, calculated on a daily basis, equals or exceeds the subscription fee of the previous plan,
regardless of the pricing for usage-based charges.
When a subscription is upgraded:
* Lago promptly applies the new plan to the customer; and
* In the case of a subscription that is paid in advance (at the beginning of the period), Lago issues a credit note for the unused days from the former plan.
## Downgrades behavior
A downgrade occurs when the subscription fee of the new plan, calculated on a daily basis is lower than the subscription fee of the previous plan,
regardless of the pricing for usage-based charges.
When a subscription is downgraded:
* The new plan is applied at the end of the current billing period to ensure that your customer fully benefits from the plan they have already paid for. The newly applied plan will be in a pending state.
# Overview
Since usage-based charges can be calculated at the end of the billing period, you often need to wait to collect payments. With prepaid credits, you can now unlock recurring revenue opportunities for pay-as-you-go pricing models.
Prepaid credits increase predictability as they allow you to collect payments in advance and then monitor the evolution of the balance of your customer’s wallets.
## Create wallets[](#create-wallets "Direct link to heading")
To create a wallet for one of your customers through the user interface:
1. Access the **"Customers"** section via the side menu;
2. Select a customer from the list;
3. Open the **"Wallets"** and click **"Add a wallet & credits"** on the right;
4. Choose a name for the wallet (optional);
5. Set the credit value (e.g. 1 credit = \$5);
6. Enter the number of credits to be purchased and/or granted for free;
7. Define transaction metadata (optional & available only via API);
8. Determine whether the wallet transaction generates an invoice after a top-up or only following a successful payment;
9. Set the [expiration date](#expiration-date-and-termination) (optional); and
10. Click **"Add wallet & credits"** to confirm.
If the currency of the customer is already defined, the currency of the wallet
must be the same.
```bash Create a credit wallet
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"external_customer_id": "hooli_1234",
"name": "Prepaid credits",
"rate_amount": "1.0",
"paid_credits": "100.0",
"granted_credits": "50.0",
"currency": "USD",
"expiration_at": "2022-07-07",
"invoice_requires_successful_payment": false,
"transaction_metadata": [
{
"key": "top-up-type",
"value": "manual"
}
]
}
}'
```
![Creation of a wallet via the user interface](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/images/new-wallet.png)
Free credits are added to the customer's wallet instantly, while purchased
credits are added to the wallet when payment is confirmed (see below).
Each customer can only have one active wallet.
## Real time wallet balance[](#real-time-wallet-balance "Direct link to heading")
**PREMIUM FEATURE** ✨
This feature is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
Keep track of your wallet's real-time balance. Lago provides two types of balances for your wallet:
1. **Balance:** invoiced balance, which reflects the remaining prepaid credits in your wallet. It updates each time an invoice is finalized for the customer.
2. **Ongoing Balance:** balance accounted for current usage, including taxes, offering a real-time estimate of your balance's consumption. It refreshes every 5 minutes or upon the finalization of an invoice for the customer.
## Application scope[](#application-scope "Direct link to heading")
Prepaid credits are deducted from the subtotal of the next invoice(s), after
tax.
![Invoice partially paid with prepaid credits](https://mintlify.s3-us-west-1.amazonaws.com/lago-docs/guide/images/prepaid-credits-invoice-ecd9e8ad653b516efb08c6b48e1e48fe.png)
Prepaid credits do not apply to one-off invoices.
## Invoicing after successful payment option
When enabled, this option delays issuing an invoice for a wallet top-up until a successful payment is made. If disabled, the invoice is issued immediately upon the wallet top-up, regardless of the payment status. This setting applies to all transactions for the wallet, but can be overridden for individual transactions or recurring rules.
## Expiration date and termination[](#expiration-date-and-termination "Direct link to heading")
By default, if you don't set an expiration date, prepaid credits are carried
over to the next billing period until the wallet balance is zero.
If you define an expiration date, when the date is reached, all remaining
credits are **automatically voided**.
To modify the expiration date of the prepaid credits through the user interface:
1. Open the **"Wallets"** tab and click **"Edit wallet"** on the right;
2. Select **"Edit information"**;
3. Modify the expiration date; and
4. Click **"Edit information"** to confirm.
The expiration date displayed in the app is based on the organization's timezone.
You also have the ability to terminate a wallet manually, before its expiration
date:
1. Open the **"Wallets"** tab and click **"Edit wallet"** on the right;
2. Select **"Terminate wallet"**; and
3. Click again to confirm.
Terminating a wallet will instantly void all remaining credits. This action
**cannot be undone**.
# Top-up and void credits
Add and void credits, to the customer's wallet.
## Credit purchases and top-ups[](#credit-purchases-and-top-ups "Direct link to heading")
Lago automatically generates an invoice for each purchase. Taxes do not apply to
credit purchases, which are considered as advance payments.
Payment must be made in order for credits to be added to the customer's wallet
(i.e. the status of the invoice must be `succeeded`).
To top up a wallet through the user interface:
1. Open the **"Wallets"** tab and click **"Edit wallet"** on the right;
2. Select **"Top up credit"**;
3. Enter the number of credits to be purchased and/or granted for free;
4. Define transaction metadata (optional & available only via API);
5. Determine whether the wallet transaction generates an invoice after a top-up or only following a successful payment; and
6. Click **"Top up credit"** to confirm.
Coupons **do not apply** to credit purchases and top-ups.
```bash Top up a credit wallet
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallet_transactions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet_transaction": {
"wallet_id": "wallet_1234567890",
"paid_credits": "20.0",
"granted_credits": "10.0",
"invoice_requires_successful_payment": false,
"metadata": [
{
"key": "top-up-type",
"value": "manual"
}
]
}
}'
```
## Invoicing top-up after successful payment option
When enabled, this option delays issuing an invoice for a wallet top-up until a successful payment is made. If disabled, the invoice is issued immediately upon the wallet top-up, regardless of the payment status.
This setting can be applied to individual transactions.
## Void credits[](#void-credits "Direct link to heading")
You can deduct a specific number of credits from the wallet's balance. Note that this action is instantaneous and cannot be undone.
To top up a wallet through the user interface:
1. Open the **"Wallets"** tab and click **"Edit wallet"** on the right;
2. Select **"Void credits"**;
3. Enter the number of credits to void;
4. Define transaction metadata (optional & available only via API); and
5. Click **"Void credits"** to confirm.
```bash Top up a credit wallet
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallet_transactions" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet_transaction": {
"wallet_id": "wallet_1234567890",
"voided_credits": "20.0",
"metadata": [
{
"key": "top-up-type",
"value" "manual-void"
}
]
}
}'
```
## Setup recurring top-ups
When creating or editing a wallet, you have the option to enable recurring top-ups. Two methods for recurring top-ups are available: `fixed` and `target`. These can be triggered either based on an `interval` or a `threshold`.
### Fixed recurring top-up
A fixed recurring top-up allows you to add a predetermined number of credits to your wallet, either for purchasing or gifting.
### Target recurring top-up
A target recurring top-up allows you to add a variable amount of credits to your wallet to reach a specific target balance. The top-up amount is determined by the ongoing balance at the trigger moment and the desired target balance.
### Interval trigger
For an `interval` trigger, specify the frequency of the automatic top-up: `weekly`, `monthly`, `quarterly` or `yearly`.
Once the interval is defined, the system will automatically perform a top-up:
* Weekly, on the same day each week (e.g., every Monday).
* Monthly, on the same date each month (e.g., every 2nd of the month).
* Quarterly, on the same date every three months (e.g., every 2nd of the quarter).
* Yearly, on the same date every year (e.g., every 2nd of January).
To setup a `interval` recurring top-up through the user interface:
1. Create or edit a wallet;
2. Trigger on the option `Activate recurring top-up`;
3. Select `interval` as recurring type;
4. Define your interval;
5. Define when the rule should start; and
6. Define transaction metadata for the top-ups (optional & available only via API);
```bash Setup an interval recurring top-up
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"external_customer_id": "hooli_1234",
"name": "Prepaid credits",
"rate_amount": "1.0",
"paid_credits": "0.0",
"granted_credits": "0.0",
"currency": "USD",
"expiration_at": "2022-07-07",
"recurring_transaction_rules": [
{
"method": "fixed"
"trigger": "interval",
"interval": "weekly",
"started_at": null,
"paid_credits": "100.0",
"granted_credits": "0.0",
"invoice_requires_successful_payment": false,
"transaction_metadata": [
{
"key": "top-up-type",
"value": "automatic"
}
]
}
]
}
}'
```
### Threshold trigger
With a `threshold` trigger, set a specific number of `credits` that will trigger an automatic top-up. Lago monitors the `ongoing balance`, and if it falls below the defined credit threshold, an automatic top-up is initiated.
To setup a `interval` recurring top-up through the user interface:
1. Create or edit a wallet;
2. Trigger on the option `Activate recurring top-up`;
3. Select `threshold` as recurring type;
4. Define the credits threshold; and
5. Define transaction metadata for the top-ups (optional & available only via API);
```bash Set a recurring top-up on creation
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"external_customer_id": "hooli_1234",
"name": "Prepaid credits",
"rate_amount": "1.0",
"paid_credits": "100.0",
"granted_credits": "50.0",
"currency": "USD",
"expiration_at": "2022-07-07",
"recurring_transaction_rules": [
{
"method": "fixed"
"trigger": "threshold",
"threshold_credits": "100.0"
"paid_credits": "100.0",
"granted_credits": "0.0",
"invoice_requires_successful_payment": true,
"transaction_metadata": [
{
"key": "top-up-type",
"value": "automatic"
}
]
}
]
}
}'
```
# Webhooks
When using Lago, the app generates [several events](/api-reference/webhooks/messages) that you can listen to in order to trigger workflows. Each time an event is generated, you can view it in the Lago application using the webhook logs. This allows you to take a closer look at the generated events, detect possible errors, and retry them.
## Adding a webhook URL
To add a webhook endpoint via the Lago app, follow these steps:
1. Go to the **Developers** section via the sidebar;
2. Open the **Webhooks** tab;
3. Click **Add a webhook**;
4. Enter the webhook URL;
5. Choose the webhook signature between JWT and HMAC; and
6. Click **Add webhook** to confirm.
Note that you can add up to 5 webhook endpoints.
## The webhook signature
By creating a webhook endpoint, you have two signature options.
* The first is `JWT`, with a possibly lengthy payload header and potential size limits;
* The second is `HMAC`, which features a shorter payload header and no size restrictions.
```bash Choosing the webhook signature
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/webhook_endpoints" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"webhook_endpoint": {
"webhook_url": "https://foo.bar",
"signature_algo": "hmac"
}
}'
```
## Accessing the webhook logs
Once a webhook is registered in the app, you can access the webhook logs:
1. Go to the **Developers** section via the sidebar;
2. Open the **Webhooks** tab;
3. Click on the webhook endpoint to see the list of events; and
4. Click the reload icon to see new events (optional).
## Accessing a specific event
You can see the details of a specific event by clicking on it. Depending on the event status, you will have access to two or three main blocks:
1. **A list of properties, including:**
1. **Timestamp:** the timestamp of the event;
2. **Webhook URL:** the URL used to listen to events;
3. **Unique key:** idempotency key associated with the event;
4. **Webhook type:** the webhook type used to understand the action triggered;
5. **Response:** the response code (i.e. acknowledgement of receipt);
6. **Number of retries:** if the event failed, the number of retries attempted;
2. **A JSON snippet with the arguments sent by Lago; and**
3. **If the event failed, an error response will be included.**
## Errors and retries
Your webhook server should response with a 2xx (`200`, `201`, `202`, `204`) status code to acknowledge the receipt of the event. If the response is not supported as a success, Lago will consider it as failed.
Some events generated by Lago may not be received on the user side, which is why Lago displays an error status in the user interface.
# NetSuite
Lago seamlessly integrates with NetSuite, enabling real-time synchronization of billing data with your preferred accounting tool.
**PREMIUM ADD-ON** ✨
This integration is available upon request only. Please **[contact us](mailto:hello@getlago.com)** to get access to this premium integration.
## RESTlet script configuration
Lago's native integration with NetSuite utilizes a [custom RESTlet script](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4618456517.html) to provide maximum flexibility in fetching or pushing billing data. To set up the Lago RESTlet script in your NetSuite instance, follow these steps:
### Upload Lago Scripts
1. In NetSuite, go to **Documents > Files > File Cabinet**;
2. Under `SuiteScripts`, create a new folder named `Lago`;
3. **Upload `ramda.min.js`**: This library is essential for using Lago and can be downloaded from [here](https://github.com/ramda/ramda/blob/master/dist/ramda.min.js); and
4. Upload another file into the `Lago` folder and **paste the script provided by your Lago Account Manager**.
### Deploy Lago Scripts
1. Navigate to **Customization > Scripting > Scripts > Create a New Script**;
2. Deploy the Lago script for **All roles** and **All employees** (you can create custom roles if needed); and
3. Make sure to change the script status to `released`.
By deploying this script, you'll generate a **custom endpoint url** that is crucial for the authentication process and enables seamless data synchronization between Lago and NetSuite.
## Mandatory NetSuite settings
To ensure the sync doesn't fail, verify that the following settings are correctly configured. This will enable Lago to sync data to NetSuite properly.
### Remove Locations on invoices and credit memos
Lago doesn't recognize the location field on invoices, which is mandatory by default. To resolve this, remove the location requirement from your invoice form:
1. Navigate to **Customization > Forms > Transaction Forms**;
2. Locate the form related to your invoices;
3. Go to the **Screen Fields** tab; and
4. Find the Location field and **uncheck both the Show and Mandatory checkboxes**.
You can repeat the same operation for Credit Memos
### Create Lago Tax Nexus, Type and Code
To have Lago override the tax details for your invoice line items, follow these steps. If not, Lago will send the amount excluding taxes to NetSuite.
1. Go to **Setup** > **Tax** > **Nexuses** > **New**;
2. Choose a brand new **Nexus** (⚠️ ensure it's unused by other existing tax nexuses. It can be a new state for an existing country, or a new country.);
3. Enter `Lago Tax Nexus` in the **Description** field;
4. Create a new **Tax Agency** by clicking the **+** button. Name it `Lago Tax Agency` and assign it to the relevant parent subsidiary;
5. Save your new Nexus;
6. Add this newly created Nexus to the targeted NetSuite Subsidiaries by navigating to **Setup > Company > Subsidiaries**. Select the parent subsidiary, and add this new nexus in the **Tax Registrations** tab; and
7. Ensure that the tax engine for this registration is set to `SuiteTax Engine`.
1. Navigate to **Setup** > **Tax** > **Tax Types** > **New**;
2. Select the same **Country** as the one used in the Lago Tax Nexus;
3. Name it `Lago Tax Type`;
4. **Link the Lago Tax Nexus** in the Nexus section;
5. Add a **Payables Account** and a **Receivables Account** to this new Tax Type; and
6. Save it.
1. Go to **Setup** > **Tax** > **Tax Code** > **New**;
2. Enter a **Name**, like `Lago Tax`;
3. Select and tie the previously created Lago Tax Type; and
4. Save your settings.
### Define Taxable items
To enable tax amount overrides for your Lago invoices synced to NetSuite, ensure all items are marked as taxable. If any item is non-taxable, the invoice sync will fail. To update an item:
1. Go to **Lists > Accounting > Items**;
2. Edit the item associated with a Lago object;
3. Navigate to the **Accounting** tab;
4. Locate the **Tax / Tariff** section; and
5. Set the item to **Taxable**.
## Connecting Lago to NetSuite
To fully integrate Lago with NetSuite, start by connecting your Lago instance to a new NetSuite connection.
You can have an unlimited number of NetSuite connections. First, link your NetSuite account to Lago.
Once connected, activate the specific syncs and actions required for your use case.
This ensures that your Lago instance is properly configured to communicate with NetSuite, enabling seamless data synchronization and management.
### Create a new integration in NetSuite
After logging into your NetSuite account, navigate to **Setup > Integration > Manage Integrations > New**.
Enter the required integration details and follow these steps:
* Make sure the [oAuth feature is enabled](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157771482304.html#To-enable-OAuth-2.0-feature%3A) for your NetSuite instance;
* Make sure the *SOAP WEB SERVICES* and *REST WEB SERVICES* features are enabled in **NetSuite > Company > Enable Features > SuiteCloud**;
* Under Authentication, select **TOKEN-BASED AUTHENTICATION**;
* Disable *TBA: AUTHORIZATION FLOW* and *AUTHORIZATION CODE GRANT*; and
* Save your new integration.
The Client Credentials will be displayed. **Copy the `Consumer Key/Client ID` and `Consumer Secret/Client Secret`** and save them in a secure document for future reference, as this information will not be accessible once you leave the screen.
### Create a new access token in NetSuite
* Log into your NetSuite account and navigate to the homepage by **clicking the home icon**;
* In the **Settings** section at the bottom left corner, locate and click the **Manage Access Tokens** button;
* Select the **Application Name** created for this integration;
* Enter a **token Name**; and
* Save your new access token.
The Token Credentials will be displayed. **Copy the `Token ID` and `Token Secret`** and save them in a secure document for future reference, as this information will not be accessible once you leave the screen.
### Authentication flow
The authentication process connects Lago and NetSuite through OAuth2.
To establish this connection, you need to provide the following mandatory fields:
* **Connection Name:** an internal name for the connection within Lago;
* **Unique Connection Code:** an internal code for the connection within Lago;
* **NetSuite Account ID:** your NetSuite [account identifier](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1498754928.html#:~:text=You%20can%20find%20your%20NetSuite,an%20underscore%2C%20for%20example%20123456_RP.);
* **NetSuite Client ID:** the [client ID](/integrations/accounting/netsuite#create-a-new-integration-in-netsuite) from your NetSuite account;
* **NetSuite Client Secret:** the [client secret](/integrations/accounting/netsuite#create-a-new-integration-in-netsuite) from your NetSuite account;
* **NetSuite Token Id:** the [token ID](/integrations/accounting/netsuite#create-a-new-access-token-in-netsuite) from your NetSuite account;
* **NetSuite Token Secret:** the [token secret](/integrations/accounting/netsuite#create-a-new-access-token-in-netsuite) from your NetSuite account;
* **Custom RESTlet Endpoint:** The endpoint created from the [custom RESTlet script](/integrations/accounting/netsuite#restlet-script-configuration).
### Enable actions and syncs
Here is a list of syncs and actions that Lago uses with NetSuite. Some are mandatory, while others are optional:
* `Accounts`: Fetch account data from NetSuite *(mandatory)*;
* `Customers`: Syncs or fetch customer data from NetSuite *(mandatory)*;
* `Items` and `Tax Items`: Fetch item and tax item data from NetSuite *(mandatory)*;
* `Invoices`: Syncs invoice data to NetSuite *(mandatory)*;
* `Sales Orders`: Syncs sales order data to NetSuite *(optional)*;
* `Credit Notes`: Syncs credit note data to NetSuite *(optional)*; and
* `Payments`: Syncs payment data to NetSuite *(optional)*.
## Mapping items between Lago and NetSuite
To sync invoices, credit notes, sales orders, and payments to NetSuite, Lago establishes a one-to-one relationship between Lago objects and NetSuite objects.
Follow these steps to map an item:
* **Access a NetSuite Connection in Lago:** navigate to your connected NetSuite integration within the Lago platform;
* **Select the Item to map:** click on the specific item in Lago that you wish to map to a corresponding NetSuite item;
* **Fetch Items from NetSuite:** Lago will automatically retrieve the relevant items from your NetSuite instance;
* **Map the Item:** choose the appropriate NetSuite item from the list provided by Lago; and
* **Click 'Save'** to finalize the mapping.
### Mapping a fallback item (mandatory)
The fallback item is a dummy item used as a backup in case the mapping of other objects fails.
To ensure continuous data synchronization between Lago and NetSuite, this fallback item will be used whenever there is a mapping issue.
This mapping follows a one-to-many structure, meaning that a single fallback item can be used to handle multiple mapping issues.
### Mapping a tax item
To override the tax amount for an invoice, sales order, or credit note, you need to map a single tax item from NetSuite.
This mapped item will be used to assign the correct tax amount.
**To ensure taxes are sent from Lago to NetSuite, complete the tax mapping** for the following [tax fields you created here](#create-lago-tax-nexus-type-and-code):
1. Tax Nexus;
2. Tax Type; and
3. Tax Code.
Use the `id` for each item, found either in the UI or in the URL of the specific item.
This mapping follows a one-to-many structure, meaning that a single tax item can be mapped to override all tax amounts issued by Lago.
### Mapping default objects
Coupons, credit notes, subscription fees, minimum commitments, and prepaid credits require a one-to-many mapping.
Each of these objects must be mapped to a single default item from your NetSuite instance. Lago will use this mapped item
whenever any of these objects appear on the final invoice sent to NetSuite.
This mapping follows a one-to-many structure, meaning a single item can handle multiple mappings for coupons, credit notes, subscription fees, minimum commitments, and prepaid credits.
### Mapping custom objects
Billable metrics and add-ons require a one-to-one mapping. Each billable metric, used for usage-based billing, must represent a specific SKU in your NetSuite instance.
You need to map each of these individually. Lago will use the mapped items whenever any of these metrics or add-ons appear on the final invoice sent to NetSuite.
This mapping follows a one-to-one structure, meaning each billable metric or add-on must be mapped to a specific NetSuite item.
## Customers synchronization
When creating or updating a Lago customer, you can choose to link it to a NetSuite customer.
The first option is to **automatically create a new customer from Lago to NetSuite**. Follow these steps:
1. Create or update a new Lago customer;
2. Select the targeted NetSuite connection;
3. Check the box labeled 'Create this customer automatically in NetSuite';
4. Choose a NetSuite subsidiary from the list (Lago will fetch the list of subsidiaries from your NetSuite instance); and
5. Save and create this new customer.
If the customer is successfully created in NetSuite, a new field will be displayed in the Lago customer view, providing a direct link to the corresponding NetSuite customer.
Customer creation from Lago to NetSuite happens in real-time with only a few seconds of delay.
The second option is to **import an existing NetSuite customer to a Lago customer**. Follow these steps:
1. Create or update a Lago customer;
2. Select the targeted NetSuite connection;
3. Ensure the box labeled 'Create this customer automatically in NetSuite' is unchecked;
4. Paste the NetSuite customer ID in the appropriate field; and
5. Save and create this new customer.
**Here is the list of fields that is currently synced to NetSuite:**
| Lago | NetSuite |
| --------------------------------- | ------------------------ |
| customer | type |
| customer.name | companyname |
| customer.netsuite\_subsidiary | subsidiary |
| customer.id | custbody\_lago\_id |
| customer.email | email |
| customer.phone | phone |
| customer.external\_salesforce\_id | custentity\_lago\_sf\_id |
## Invoices synchronization
If a Lago customer is linked to a NetSuite customer, Lago syncs invoices to NetSuite Invoices in real-time.
It's important to note the following:
* Each fee issued by Lago is synced as a line item on a NetSuite invoice;
* The Lago fee `units` are synced to NetSuite as `quantity`;
* The Lago fee `precise_unit_amount` is synced to NetSuite as `rate`;
* Lago overrides the total tax amount of a NetSuite invoice using the tax item, as NetSuite does not support tax details at the line item level; and
* Any discounts on an invoice (coupon, credit note, or prepaid credits) are synced as negative line items on the NetSuite invoice.
If the invoice is successfully created in NetSuite, a new field will be displayed in the Lago invoice view, providing a direct link to the corresponding NetSuite invoice.
Invoice creation from Lago to NetSuite happens in real-time with only a few seconds of delay.
**Here is the list of fields that is currently synced to NetSuite:**
| Lago | NetSuite |
| --------------------------------- | ------------------ |
| invoice | type |
| invoice.lago\_id | tranid |
| customer.netsuite\_internal\_id | entity |
| true | istaxable |
| taxitem.id | taxitem |
| invoice.taxes\_amount\_cents | taxamountoverride |
| invoice.number | otherrefnum |
| invoice.lago\_id | custbody\_lago\_id |
| invoice.fee.id | lineItems.item |
| invoice.fee.account\_code | lineItems.account |
| invoice.fee.units | lineItems.quantity |
| invoice.fee.precise\_unit\_amount | lineItems.rate |
## Sales Orders synchronization
If a Lago customer is linked to a NetSuite customer and the Sales Orders action is enabled in your Lago-NetSuite connection, Lago syncs invoices to NetSuite Sales Orders in real-time.
Note that the same fields used to sync invoices are also used to sync sales orders.
**Here is the list of fields that is currently synced to NetSuite:**
| Lago | NetSuite |
| --------------------------------- | ------------------ |
| salesorder | type |
| invoice.lago\_id | tranid |
| customer.netsuite\_internal\_id | entity |
| true | istaxable |
| taxitem.id | taxitem |
| invoice.taxes\_amount\_cents | taxamountoverride |
| invoice.number | otherrefnum |
| invoice.lago\_id | custbody\_lago\_id |
| invoice.fee.id | lineItems.item |
| invoice.fee.account\_code | lineItems.account |
| invoice.fee.units | lineItems.quantity |
| invoice.fee.precise\_unit\_amount | lineItems.rate |
## Credit Notes synchronization
If a Lago customer is linked to a NetSuite customer, Lago syncs credit notes to NetSuite Credit Memos in real-time.
It's important to note the following:
* Each fee refunded by Lago is synced as a line item on a NetSuite Credit Memo;
* Lago overrides the total tax amount of a NetSuite credit memo using the tax item, as NetSuite does not support tax details at the line item level; and
* Any discounts on an credit note (like coupon, for instance) are synced as line items on the NetSuite Credit Memo.
If the credit note is successfully created in NetSuite, a new field will be displayed in the Lago credit note view, providing a direct link to the corresponding NetSuite Credit Memo.
Credit note creation from Lago to NetSuite happens in real-time with only a few seconds of delay.
**Here is the list of fields that is currently synced to NetSuite:**
| Lago | NetSuite |
| --------------------------------- | ------------------ |
| creditmemo | type |
| invoice.lago\_id | tranid |
| customer.netsuite\_internal\_id | entity |
| true | istaxable |
| taxitem.id | taxitem |
| invoice.taxes\_amount\_cents | taxamountoverride |
| invoice.number | otherrefnum |
| invoice.lago\_id | custbody\_lago\_id |
| invoice.fee.id | lineItems.item |
| invoice.fee.account\_code | lineItems.account |
| invoice.fee.units | lineItems.quantity |
| invoice.fee.precise\_unit\_amount | lineItems.rate |
## Payments synchronization
If a Lago invoice is tied to a NetSuite invoice, Lago automatically syncs payments occurring in Lago to NetSuite, updating in-real time the payment status of the invoice in NetSuite.
| Lago | NetSuite |
| ------------------------------- | ---------------- |
| customerpayment | type |
| customer.netsuite\_internal\_id | customer |
| invoice.netsuite\_internal\_id | lineItems.doc |
| true | lineItems.apply |
| invoice.total\_amount\_cents | lineItems.amount |
## Integration logs
Whenever an issue occurs in NetSuite, Lago will notify you through a [webhook message](/api-reference/webhooks/messages#accounting-provider-error) called `customer.accounting_provider_error`.
# Xero
Lago seamlessly integrates with Xero, enabling real-time synchronization of billing data with your preferred accounting tool.
**PREMIUM ADD-ON** ✨
This integration is available upon request only. Please **[contact us](mailto:hello@getlago.com)** to get access to this premium integration.
## Connecting Lago to Xero
To fully integrate Lago with Xero, start by connecting your Lago instance to a new Xero connection.
You can have an unlimited number of Xero connections. First, link your Xero account to Lago.
Once connected, activate the specific syncs and actions required for your use case.
This ensures that your Lago instance is properly configured to communicate with Xero, enabling seamless data synchronization and management.
1. In Lago, navigate to **Integrations > Xero**;
2. Create a **new Xero connection**;
3. Assign a unique **name** and **code** to the connection; and
4. Use OAuth2 to **grant access** to your Xero instance.
There you go, Lago is fully connected to Xero!
## Enable actions and syncs
Here is a list of syncs and actions that Lago uses with Xero. Some are mandatory, while others are optional:
* `Accounts`: Fetch account data from Xero *(mandatory)*;
* `Customers`: Syncs or fetch customer data from Xero *(mandatory)*;
* `Items`: Fetch item data from Xero *(mandatory)*;
* `Invoices`: Syncs invoice data to Xero *(mandatory)*;
* `Credit Notes`: Syncs credit note data to Xero *(optional)*; and
* `Payments`: Syncs payment data to Xero *(optional)*.
## Mapping items between Lago and Xero
To sync invoices, credit notes and payments to Xero, Lago establishes a one-to-one relationship between Lago objects and Xero objects. Follow these steps to map an item:
* **Access a Xero Connection in Lago:** navigate to your connected Xero integration within the Lago platform;
* **Select the Item to map:** click on the specific item in Lago that you wish to map to a corresponding Xero item;
* **Fetch Items from Xero:** Lago will automatically retrieve the relevant items from your Xero instance;
* **Map the Item:** choose the appropriate Xero item from the list provided by Lago; and
* **Click 'Save'** to finalize the mapping.
### Mapping a fallback item (mandatory)
The fallback item is a dummy item used as a backup in case the mapping of other objects fails.
To ensure continuous data synchronization between Lago and Xero, this fallback item will be used whenever there is a mapping issue.
This mapping follows a one-to-many structure, meaning that a single fallback item can be used to handle multiple mapping issues.
### Mapping a payment account (mandatory)
To synchronize invoice payments between Lago and Xero, ensure that at least one payment account is mapped.
To set up a payment account in Xero, follow these steps:
1. Log in to your Xero instance;
2. Navigate to **Accounting > Chart of Accounts**;
3. Select an existing revenue account or create a new one; and
4. When editing or creating the account, ensure the **'Enable payments to this account'** checkbox is selected.
In Lago, you can now map it in the dedicated section '**Account linked to payments**'.
### Mapping custom objects
Billable metrics and add-ons require a one-to-one mapping. Each billable metric, used for usage-based billing, must represent a specific SKU in your Xero instance.
You need to map each of these individually. Lago will use the mapped items whenever any of these metrics or add-ons appear on the final invoice sent to Xero.
This mapping follows a one-to-one structure, meaning each billable metric or add-on must be mapped to a specific Xero item.
## Customers synchronization
When creating or updating a Lago customer, you can choose to link it to a Xero customer.
The first option is to **automatically create a new customer from Lago to Xero**. Follow these steps:
1. Create or update a new Lago customer;
2. Select the targeted Xero connection;
3. Check the box labeled 'Create this customer automatically in Xero'; and
4. Save and create this new customer.
If the customer is successfully created in Xero, a new field will be displayed in the Lago customer view, providing a direct link to the corresponding Xero customer.
Customer creation from Lago to Xero happens in real-time with only a few seconds of delay.
The second option is to **import an existing Xero customer to a Lago customer**. Follow these steps:
1. Create or update a Lago customer;
2. Select the targeted Xero connection;
3. Ensure the box labeled 'Create this customer automatically in Xero' is unchecked;
4. Paste the Xero customer ID in the appropriate field; and
5. Save and create this new customer.
**Here is the list of fields that is currently synced to Xero:**
| Lago | Xero |
| ------------------------------------ | ------------ |
| customer | type |
| customer.name | Name |
| customer.email | EmailAddress |
| customer.phone | Phones |
| customer.tax\_identification\_number | TaxNumber |
| customer.address\_line\_1 | AddressLine1 |
| customer.address\_line\_2 | AddressLine2 |
| customer.city | City |
| customer.zip | PostalCode |
| customer.country | Country |
| customer.state | Region |
## Invoices synchronization
If a Lago customer is linked to a Xero customer, Lago syncs invoices to Xero Invoices in real-time.
It's important to note the following:
* Each fee issued by Lago is synced as a line item on a Xero invoice;
* The Lago fee `units` are synced to Xero as `Quantity`;
* The Lago fee `precise_unit_amount` is synced to Xero as `UnitAmount`;
* Lago can send the total tax amount for a specific line item; and
* Lago can apply discount to a specific line item.
If the invoice is successfully created in Xero, a new field will be displayed in the Lago invoice view, providing a direct link to the corresponding Xero invoice.
Invoice creation from Lago to Xero happens in real-time with only a few seconds of delay.
**Here is the list of fields that is currently synced to Xero:**
| Lago | Xero |
| ------------------------------------------- | -------------- |
| invoice | type |
| invoice.number | InvoiceNumber |
| invoice.status | Status |
| invoice.currency | CurrencyCode |
| invoice.issuing\_date | Date |
| invoice.payment\_due\_date | DueDate |
| invoice.fee.units | Quantity |
| invoice.fee.precise\_unit\_amount | UnitAmount |
| invoice.fee.amount\_cents | LineAmount |
| invoice.fee.taxes\_amount\_cents | TaxAmount |
| invoice.fee.precise\_coupons\_amount\_cents | DiscountAmount |
## Credit Notes synchronization
If a Lago customer is linked to a Xero customer, Lago syncs credit notes to Xero Credit Notes in real-time.
It's important to note the following:
* Each fee refunded by Lago is synced as a line item on a Xero Credit Note; and
* Any discounts on an credit note (like coupon, for instance) are synced as line items on the Xero Credit Note.
If the credit note is successfully created in Xero, a new field will be displayed in the Lago credit note view, providing a direct link to the corresponding Xero Credit Note.
Credit note creation from Lago to Xero happens in real-time with only a few seconds of delay.
**Here is the list of fields that is currently synced to Xero:**
| Lago | Xero |
| --------------------------------------------- | ---------------- |
| credit\_note.number | CreditNoteNumber |
| credit\_note.reference | Reference |
| credit\_note.status | Status |
| credit\_note.currency | CurrencyCode |
| credit\_note.issuing\_date | Date |
| credit\_note.line\_item.units | Quantity |
| credit\_note.line\_item.precise\_unit\_amount | UnitAmount |
| credit\_note.line\_item.amount\_cents | LineAmount |
| credit\_note.line\_item.taxes\_amount\_cents | TaxAmount |
## Payments synchronization
If a Lago invoice is tied to a Xero invoice, Lago automatically syncs payments occurring in Lago to Xero, updating in-real time the payment status of the invoice in Xero.
| Lago | Xero |
| --------------------- | ------- |
| invoice.id | Invoice |
| invoice.amount\_cents | Amount |
## Integration logs
Whenever an issue occurs in Xero, Lago will notify you through a [webhook message](/api-reference/webhooks/messages#accounting-provider-error) called `customer.accounting_provider_error`.
# N8N
Here is a typical use case of using Lago and N8N to create powerful alerting automation.
## Overconsumption Alerting Example (with N8N)
When one of your customers is overconsuming during a period, you might need to warn her. This might happen for Cloud or API products. Automatic billing does not mean that your customers should have a bad surprise when opening their invoices.
Here is a full workflow to create an alerting system based on your customers' current usage, using [N8N](https://n8n.io/), a powerful automation tool for developers.
In this example, we are going to build an alert anytime a usage threshold is overcome. Here is a summary of this workflow:
1. Use a **Cron** expression to call the Lago API every X minutes/hours/days
2. Call the [**Current usage**](/api-reference/customer-usage/get-current) endpoint available in Lago to fetch your customers' current usage;
3. Create a **IF statement** to condition the trigger (in our case, messages are triggered above a specific overconsumption); and
4. **Send a message** whenever this threshold is reached. You could use an emailing tool, Slack or a CRM. In our case, we are using Slack.
## 1st Node - CRON expression to repeat tasks at a defined interval
The first node is repeatedly and automatically triggering the automation at a defined interval.
1. Add a new **Node**;
2. Select **CRON** as a new application node;
3. The **Mode** is set to `Every X`; and
4. The **Value** is defined to `10` and the the **Units** to `minutes`.
This will trigger the flow automatically every 10 minutes. You can obviously change the value and the units to your preferred interval.
## 2nd Node - Catch customers' current usage with a HTTP Request
This node is used to fetch current usage from Lago API, using a HTTP request.
1. Add a new **Node**;
2. Select **HTTP Request** as a new application node;
3. Fetch [customers' current usage](/api-reference/customer-usage/get-current) from Lago API;
4. Make sure to set the `API_KEY` and the `Content-Type` as headers of your request; and
5. Execute the node to fetch the payload from Lago's API.
## 3rd Node - IF conditional statement to trigger messages under conditions
This node is used to trigger the alert only when your customers overcome a threshold of usage. Those limits depend on your product and your paying features.
In our present use case, we want to trigger an alert **when the total consumption of usage-based features overcomes \$200**. You could also use the `number of units` consumed or another useful value from the payload.
1. Add a new **Node**;
2. Select **IF** as a new application node;
3. Create a condition for the **TRUE** branch (when conditions are met);
4. The **Value** is the parameter of your condition (in our case the `amount_cents` of the current usage);
5. The **Operation** is the math operation you want to apply (in our case, condition is met when the total `amount_cents` is larger or equal to \$200);
It is important to mention that:
* You can add as many conditions as you need;
* You could add an action when the condition is `FALSE`.
## 4th Node - Send an alert message to Slack
This last node is used to trigger the message. In the example, we use a Slack channel, but you could even decide to send an email directly to your customers when they pass the limits of usage.
1. Add a new **Node**;
2. Select **Slack** as a new application node;
3. Select the targeted **Slack Account** & **Slack Channel**;
4. Choose the option to **POST** a **Message**; and
5. **Define a message** and use the variables of your payload to give context to your customers about their current usage.
On top of connecting your Slack account, don't forget to authorize the application's bot to post messages to the targeted channel.
# Zapier
Here is a typical use case of using Lago with Zapier to create powerful alerting automation.
## Invoice Alerting Example (with Zapier)
In this example, we are going to **build an alert anytime a new invoice is emitted**. To create this workflow, we are using:
1. Lago's webhook when a new invoice is emitted;
2. Zapier as an automation tool, to catch, tranform and send the data; and
3. Slack as the "receiver" to alert your team anytime a new invoice is created.
## 1. Catch a webhook when a new invoice is emitted
Lago automatically creates an invoice when a billable period is over. The invoice's payload gives you a detailed view of what has been invoiced. The first action we need to perform is to catch this invoice with a webhook:
1. In Zapier, create a new Zap;
2. Use the **Webhooks by Zapier** as the trigger of this Zap;
3. Select the **Catch Raw Hook** event trigger;
4. Copy the Zapier Webhook URL and paste it in Lago (**Developers** > **Webhooks** > **Add a webhook**); and
5. Catch your first webhook when an invoice is emitted (whenever you assign an add-on or a subscription).
## 2. Run a script to transform the webhook
In Zapier, create a second action by clicking the `+` icon. This new event action is used to format the webhook with a breakdown of fields that can be used in a message.
1. Select **Code by Zapier** as a new *Event Action*;
2. Click on **Javascript** as the event code language to run;
3. Create a field called `payload`. The value of this field is the full **Raw body** of your invoice object received);
4. Run the script (code snippet below) in the **Code** section;
5. Test the action. If valid, it returns a breakdown of fields.
```javascript
var obj = JSON.parse(inputData.payload);
if(obj.object_type == "invoice"){
return obj
}
```
## 3. Send a message to a Slack Channel
Once you catch the breakdown of fields returned by the invoice payload, you can easily use them to create a Slack text message.
In Zapier, create a third action by clicking the `+` icon. This new event action is used to send a message to Slack by using the fields of the invoice payload.
1. Select **Slack** as a new app action;
2. Select the **Send Channel Message** action;
3. Choose the targeted **Slack Account**;
4. Choose the targeted **Slack Channel**; and
5. Create a message by using the fields returned by the payload.
By testing and validating the entire Zap, a Slack message is sent anytime a new invoice is emitted by Lago. You can use the same message example as detailed below:
# HubSpot
Lago syncs billing data to HubSpot in real-time.
**PREMIUM ADD-ON** ✨
This integration is only available to users with a specific paying add-on. Please
**[contact us](mailto:hello@getlago.com)** to get access to HubSpot CRM integration.
This integration is a one-way sync, where Lago continuously syncs billing data to HubSpot in real time.
Currently, it doesn’t support fetching information or taking actions from HubSpot back to Lago.
## Object mapping
As Lago needs to sync billing data to HubSpot custom objects, your HubSpot account needs to be on the **Sales Hub Enterprise** plan.
## Integration configuration
### oAuth connection
To fully integrate Lago with HubSpot, start by connecting your Lago instance to a new HubSpot connection. You can have an unlimited number of HubSpot connections. First, link your HubSpot account to Lago. Once connected, activate the specific syncs and actions required for your use case. This ensures that your Lago instance is properly configured to communicate with HubSpot, enabling seamless data synchronization and management.
1. In Lago, navigate to **Integrations** > **HubSpot**;
2. Create a **new HubSpot connection**;
3. Assign a unique **name** and **code** to the connection;
4. Select the **default targeted object** for Lago customers between HubSpot Contacts or Companies; and
5. Use OAuth2 to grant access to the desired HubSpot account.
There you go, Lago is fully connected to HubSpot!
### List of scopes
Here's a list of scopes you grant to Lago when connecting your HubSpot instance: `oauth`, `crm.objects.companies.read`, `crm.objects.companies.write`,
`crm.objects.custom.read`, `crm.objects.custom.write`, `crm.schemas.companies.read`, `crm.schemas.companies.write`, `crm.schemas.custom.read`,
`crm.objects.contacts.read`, `crm.objects.contacts.write`, `crm.schemas.contacts.read`, `crm.schemas.contacts.write` and `crm.schemas.custom.write`.
### Custom properties deployment
By connecting HubSpot to Lago, **custom properties are automatically added to both your HubSpot Companies and Contacts** (native objects).
These fields are used to sync customer data between HubSpot and Lago.
* `lago_customer_id`: internal id of a Lago customer (unique);
* `lago_customer_external_id`: your customer's external id in Lago;
* `lago_billing_email`: your customer's billing email in Lago;
* `lago_tax_identification_number`: your customer's tax identification number in Lago; and
* `lago_customer_link`: the URL path to the related Lago customer.
Note that custom properties are deployed in the background the first time the connection is created.
### Custom objects deployment
By connecting HubSpot to Lago, 2 custom objects are automatically deployed to your HubSpot instance: `LagoSubscriptions` and `LagoInvoices`.
Note that custom objects are deployed in the background the first time the connection is created. They are automatically tied to HubSpot Contacts or Companies.
#### LagoSubscriptions
Here is the list of properties deployed with the `LagoSubscriptions` custom object:
| HubSpot Property Name | Type | Field Type | Has Unique Value |
| -------------------------------- | ----------- | ---------- | ---------------- |
| Lago Subscription Id | string | text | true |
| Lago External Subscription Id | string | text | false |
| Lago Subscription Name | string | text | false |
| Lago Subscription Plan Code | string | text | false |
| Lago Subscription Status | string | text | false |
| Lago Subscription Created At | date | date | false |
| Lago Subscription Started At | date | date | false |
| Lago Subscription Ending At | date | date | false |
| Lago Subscription At | date | date | false |
| Lago Subscription Terminated At | date | date | false |
| Lago Subscription Trial Ended At | date | date | false |
| Lago Subscription Link | string | file | false |
| Lago Billing Time | enumeration | radio | false |
#### LagoInvoices
Here is the list of properties deployed with the `LagoInvoices` custom object:
| HubSpot Property Name | Type | Field Type | Has Unique Value |
| ------------------------------------- | ------ | --------------- | ---------------- |
| Lago Invoice Id | string | text | true |
| Lago Invoice Number | string | text | false |
| Lago Invoice Issuing Date | date | date | false |
| Lago Invoice Payment Due Date | date | date | false |
| Lago Invoice Payment Overdue | bool | booleancheckbox | false |
| Lago Invoice Type | string | text | false |
| Lago Invoice Status | string | text | false |
| Lago Invoice Payment Status | string | text | false |
| Lago Invoice Currency | string | text | false |
| Lago Invoice Total Amount | number | number | false |
| Lago Invoice Subtotal Excluding Taxes | number | number | false |
| Lago Invoice File URL | string | file | false |
| Lago Invoice Link | string | file | false |
## Sync data from Lago to HubSpot
### Sync customers to HubSpot
When you create or update a customer in Lago, the information is synced in real time to your HubSpot account. Please note the following:
* If `customer.customer_type` in Lago is `company`, the data is synced as a HubSpot Company record.
* If `customer.customer_type` in Lago is `individual`, the data is synced as a HubSpot Contact record.
* If `customer.customer_type` is undefined, the data is synced using the default Customer Object set at the connection level.
You can instruct Lago to automatically create a new Company or Contact in your HubSpot account, or link an existing one by pasting a HubSpot ID into the corresponding Lago customer record.
### Sync subscriptions to HubSpot
Whenever a Lago customer is linked to a HubSpot Contact or Company, **Lago Subscriptions are automatically synced in real-time with the `LagoSubscriptions` object in HubSpot**.
The subscription record is then automatically associated with the corresponding Contact or Company in HubSpot.
### Sync invoices to HubSpot
Whenever a Lago customer is linked to a HubSpot Contact or Company, **Lago Invoices are automatically synced in real-time with the `LagoInvoices` object in HubSpot**.
The invoice record is then automatically associated with the corresponding Contact or Company in HubSpot.
# Salesforce CPQ
Lago syncs billing data to Salesforce in real-time.
**PREMIUM ADD-ON** ✨
This integration is only available to users with a specific paying add-on. Please
**[contact us](mailto:hello@getlago.com)** to get access to Salesforce CPQ integration.
This is extension package of the base package: Lago for Salesforce CRM. Base package must be installed to install CPQ package.
## Object mapping
## Pre-requisite:
* Salesforce CPQ (> Summer '19)
* Install Lago For Salesforce CRM Package [Lago Base Package](/integrations/crm/salesforce-crm)
## I. Integration configuration
### Install Salesforce CRM Package and complete Integration configuration step
* [Integration configuration ](/integrations/crm/salesforce-crm#install-salesforce-crm-package)
* [Establish and finalize connection](/integrations/crm/salesforce-crm#establish-and-finalize-connection)
### Install Salesforce CPQ Package
To gain premium access to our Salesforce Package application, please don't hesitate to contact us.
You can initiate the installation process **by clicking on the provided link**, which will direct you to the installation
page where you can follow step-by-step instructions for a seamless integration. If you have any questions or need assistance
during the installation, our dedicated support team is here to help you every step of the way.
To ensure a successful installation, please follow these steps:
1. We recommend selecting the **"Install for all users"** option;
2. Click on the **"Install" button**;
3. Make sure to **check the box to grant access to these third-party websites**; and
4. Once completed, you'll have **successfully installed** the Lago Salesforce App.
Please note that the installation process may take a few minutes to complete.
However, rest assured that you will receive an email confirmation once the installation is finished.
*
## II. Configuration to sync data
### Assign Permission:
Assign `Lago CPQ Permission` to users who needs to access Lago for Salesforce CPQ.
### Include Lago Fields in 'Quote Line Items editor' layout
Update the "Edit Line" which is available in Quote Layout to enter the details related to lago fieds in QuoteLine by following below steps:
1. Go to Setup
2. Click on Object manager
3. Go to `Quote Line` object
4. Click on \`field sets.
5. Select edit 'Line Editor\` field set.
6 Make sure following fields are available in field set:
* Lago Name
* Lago External Id
* Lago Billing Time
* Lago Start Date
* Lago End Date
## III. Actions from Salesforce to Lago
Beyond just syncing data from Lago to Salesforce, you can also initiate actions in Lago directly from Salesforce.
You can leverage Salesforce `Flows` to execute actions in Lago. Lago provides customizable templates for creating subscription from Salesforce Accounts, directly assigning subscriptions to customers from Salesforce, creating one-off invoice from salesforce.
### Create customers [from Lago to Salesforce CRM](/integrations/crm/salesforce-crm#flow-lago-template-create-customer-in-lago-on-account-create)
### Create subscriptions (automation)
Assigning a plan to a customer, adjusting negotiated prices, and initiating the subscription upon accepting a quote represents a key action from Salesforce to Lago.
To assign a subscription and set prices in Lago directly from Salesforce, use the provided two flows via following Lago Flow templates.
#### Flow 1: `LagoCPQ Template - Quote Line After Insert`
This Flow is used to update Subscription External Id if it is null
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `LagoCPQ Template - Quote Line After Insert`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers plan assignment when Lago subscription external id is null You can customize this flow to suit your specific needs.
#### Flow 2: Pre-requisite from Lago to Salesforce CRM package: `Lago Template - Create Subscription in Lago on Subscription Creation/Update`
This Flow is used to create subscriptions in Lago from Salesforce
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `Lago Template - Create Subscription in Lago on Subscription Creation/Update`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers plan assignment when `SyncToLago` checkbox is checked. You can customize this flow to suit your specific needs.
#### Flow 3: `LagoCPQ Template - Create Lago SObject Records Using Quotes`
This Flow is used to create Lago subscriptions records in Salesforce when Quote status is changed to Approved
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `LagoCPQ Template - Create Lago SObject Records Using Quotes`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers plan assignment when Quote status is changed to Approved. You can customize this flow to suit your specific needs.
### Terminate Subscription
We can terminate the subscription from Salesforce to lago only if the subscription is already synced to lago(status is *active* or *pending*).
Go to Lago Subscription record in Salesforce, and check `Terminate Subscription` checkbox.
As soon as `Terminate Subscription` is checked it will terminate the subscription in Lago. It is handled from the backend via trigger.
## Debugging & logs
To ensure seamless data synchronization between Lago and Salesforce, every action and data transfer is meticulously logged.
These logs are accessible directly through the Lago package for comprehensive debugging and analysis:
1. Navigate to 'Lago Base Configuration': This is your starting point for accessing the debugging tools. and
2. Access Logs: Click on the 'Logs' tab to view a detailed record of all activities.
You can refresh logs to keep your data current or delete unnecessary logs to maintain clarity and efficiency in the debugging process.
This approach aids in promptly identifying and resolving integration issues.
# Salesforce CRM
Lago syncs billing data to Salesforce in real-time.
**PREMIUM ADD-ON** ✨
This integration is only available to users with a specific paying add-on. Please
**[contact us](mailto:hello@getlago.com)** to get access to Salesforce CRM integration.
## Object mapping
## I. Integration configuration
### Install Salesforce CRM Package
To gain premium access to our Salesforce Package application, please don't hesitate to contact us.
You can initiate the installation process **by clicking on the provided link**, which will direct you to the installation
page where you can follow step-by-step instructions for a seamless integration. If you have any questions or need assistance
during the installation, our dedicated support team is here to help you every step of the way.
To ensure a successful installation, please follow these steps:
1. We recommend selecting the **"Install for all users"** option;
2. Click on the **"Install" button**;
3. Make sure to **check the box to grant access to these third-party websites**; and
4. Once completed, you'll have **successfully installed** the Lago Salesforce App.
Please note that the installation process may take a few minutes to complete.
However, rest assured that you will receive an email confirmation once the installation is finished.
### Webhook config: sync real-time data
After installation in Salesforce CRM, set up a webhook URL in Salesforce to receive real-time data from Lago.
This involves **configuring a new "Site" in Salesforce's setup section**.
Note that the four main actions described below should be performed by a Salesforce Admin and is only required during the initial setup.
1. Click the gear icon in the upper right to access **Salesforce Setup**;
2. Search and navigate to the Sites section; and
3. Create a new Site (see picture below).
When creating a new site, follow these steps:
1. Set a unique **Site Label**;
2. Specify a unique **Site Name**;
3. Optionally, add a **Site Description**;
4. Ensure the **Site Contact** and **Default Record Owner** are filled;
5. Set the **Default Web Address** prefix to `getPushNotification`;
6. Choose `SiteLogin` as the **Active Site Home Page**; and
7. Don't forget to **save the new site**: and
8. **Activate the newly created site** by going to the Site Details and clicking the `Activate` button.
To edit Public Access Settings for your new Site:
1. Visit the site and click **Public Access Settings**;
2. In the **Enabled Apex Class Access** section, click "edit";
3. Add `LagoWebHookSubscriptionController` to **Enabled Apex Classes**; and
4. Save your changes.
To set up the webhook URL for real-time data syncing between Lago and Salesforce, follow these steps:
1. Return to your newly created site;
2. Locate the **Custom URLs** section;
3. Copy the **domain name** *(e.g., lago.my.salesforce-sites.com)*;
4. Add the `https://` prefix to this domain name (e.g., `https://lago.my.salesforce-sites.com`); and
5. Append `/services/apexrest/lago/api/Webhooks/incoming/pushDetails/` to the domain name (e.g., `https://lago.my.salesforce-sites.com/services/apexrest/lago/api/Webhooks/incoming/pushDetails/`).
Now, go to your Lago app and past this webhook into the webhook’s settings:
1. Within Lago, navigate to **Developers**;
2. Visit the **Webhooks** tab;
3. Choose `HMAC` as the **mandatory signature type**;
4. Paste your Salesforce webhook URL; and
5. Save this webhook endpoint.
Congratulations! You're ready to sync real-time data from Lago to Salesforce! 🎉
### Establish and finalize connection
**Option 1: Configure a standard API Base URL**
To establish a connection between your Lago instance and the Salesforce Package, follow these steps:
1. Access Salesforce and locate the **App Launcher**;
2. Find and open the Lago app you recently installed;
3. Within the Lago Base Configuration tab:
* Provide your **Lago API Key** (located in Lago's Developer Section)
* Enter your Lago **API base URL**. Do not insert the `api/v1` at the end of the URL. By default, the valid URL is `https://api.getlago.com/`.
If you want to change the API base URL to another one (e.g., `https://api.eu.getlago.com/` or a custom self-hosted one), please follow option 2.
* Enter lago app URL (**Front End Base URL**). By default, the valid URL is `https://app.getlago.com/` (it will be different for self-hosted).
4. **"Save and validate"** your connection; and
* If the **Lago API Key** is valid then only **Start Data Sync** button will be enabled.
5. Click the **"Start Data Sync"** to finalize the connection between Lago and Salesforce.
Please note that data synchronization is available only for Lago customers with an `external_salesforce_id` and an existing Salesforce Account.
**Option 2: Configure a custom API Base URL**
If you use your own Lago API base URL (self-hosting) or one for a different server instance,
you can customize it directly in Salesforce:
1. Navigate to Salesforce's Setup;
2. Search for and select Remote Site Settings;
3. Find and access the remote site for the Lago App;
4. Click the Edit button to modify the remote site's details;
5. Update the Remote Site URL with your preferred URL; and
6. Save the changes.
## II. Sync data from Lago to Salesforce
If your webhook endpoint is configured correctly, your **billing data will flow seamlessly in real-time**.
Please note that Subscriptions and Invoices will be created in Salesforce via webhooks seamlessly
### Sync customers to Salesforce
To synchronize Lago Customer data with Salesforce Accounts (native object), ensure that your
Salesforce Account is created first, and that the Lago Customer's `external_salesforce_id` is explicitly populated.
1. Begin by creating a new Account in Salesforce or accessing an existing one;
2. Next, create a customer in Lago and populate the `external_salesforce_id` field for a Lago Customer with the Salesforce Account Id; and
3. Finally, your Salesforce Account and Lago Customer are synchronized!
Billing data will not sync unless these requirements are met.
Lago does not create Salesforce Accounts.
Before syncing billing data, you need to create or retrieve an existing Account in Salesforce
and populate the Lago customer field called `external_salesforce_id`.
### Sync subscriptions to Salesforce
Whenever a subscription is created for a Lago Customer, the subscription details will be automatically
synced in real-time with Salesforce using the `Lago Subscriptions` custom object.
Here is a list of Subscription fields that are automatically synced.
Note that this subcription is automatically linked to a Salesforce Account:
* Subscription Id;
* Subscription Name;
* Subscription Start Date;
* Subscription Status;
* Subscription Termination Date (synced when the subscription is terminated);
* Subscription Billing Time (either `calendar` or `anniversary`); and
* Plan Code.
### Sync invoices to Salesforce
Whenever an invoice is issued for a Lago Customer, the invoice details will be automatically
synced in real-time with Salesforce using the `Lago Invoices` custom object.
Here is a list of Subscription fields that are automatically synced:
* Invoices Number;
* Invoice Payment Status;
* Invoice Type (`subscription` or `one-off`);
* Invoice Issuing Date;
* Invoice Amount;
* Invoice File Url; and
* Invoice Currency.
### Sync credit notes to Salesforce
Whenever a credit note is issued for a Lago Invoice, the credit note details will be automatically
synced in real-time with Salesforce using the `Lago CreditNotes` custom object.
### Sync Plans, Add-Ons to Salesforce
Plans and Add-ons are synced to Salesforce when we initially click on **Start Data Sync** from Lago Base Configuration page.
* Plans are synced to `Lago Plans` object and `Product2` standard object. We also create a *price book entry* for all the products in `Standard Price Book` price book
* Add-Ons are synced to `Lago Add-Ons` object and `Product2` standard object. We also create a *price book entry* for all the products in `Standard Price Book` price book.
### Schedule Sync from Lago To Salesforce
We also provide option to schedule the data sync from Lago to Salesforce.
* `LagoSyncScheduleable` -- a schedulable class which helps us schedule either all the data or any one of them.
* To schedule the sync of any *ONE* of the object:
* Create a new instance of class by passing any one of the following string: `CUSTOMER`, `SUBSCRIPTION`, `PLAN`, `ADDON`, `INVOICE`, `CREDITNOTE`
* Ex: To sync Plans from lago to Salesforce everyday at 1PM, execute below anonymous code in Anonymous window in Developer Console. ([click here to learn more about CRON expression](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm))
```
//Create a new instance. Pass 'PLAN' in brackets.
lago.LagoSyncScheduleable syncPlan = new lago.LagoSyncScheduleable('PLAN');
//CRON expression to schedule a job everyday at 1 PM
String schedule_cron = '0 0 13 * * ?';
//schedule(name, cron_expression, class_instance)
System.schedule('Sync Lago Plan', schedule_cron, syncPlan);
```
* To schedule the sync of *ALL* the objects:
* create a new instance of class by passing `true`
* Ex: To sync **all** objects from lago to Salesforce everyday at 1PM, execute below anonymous code in Anonymous window in Developer Console. ([click here to learn more about CRON expression](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm))
```
//Create a new instance. Pass true in brackets.
lago.LagoSyncScheduleable syncAll = new lago.LagoSyncScheduleable(true);
//CRON expression to schedule a job everyday at 1 PM
String schedule_cron = '0 0 13 * * ?';
//schedule(name, cron_expression, class_instance)
System.schedule('Sync Lago all', schedule_cron, syncAll);
```
## III. Actions from Salesforce to Lago
Beyond just syncing data from Lago to Salesforce, you can also initiate actions in Lago directly from Salesforce.
You can leverage Salesforce `Flows` to execute actions in Lago. Lago provides several customizable templates for creating customers from Salesforce Accounts, directly assigning subscriptions to customers from Salesforce, creating one-off invoice from salesforce.
### Create customers
#### Flow: `Lago Template - Create Customer in Lago on Account Create`
To create a customer in Lago upon the creation of a Salesforce Account, utilize the Flow template provided by Lago.
1. Log into your Salesforce instance;
2. Access the Setup section via the settings wheel icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `Lago Template - Create Customer in Lago on Account Create`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
You have the **flexibility to modify various aspects of this flow, including the trigger conditions and field mappings**.
By default, the action is initiated when a Lago ID is absent. Additionally, you can customize how fields are mapped from your Salesforce instance to Lago.
### Create subscriptions (automation)
Assigning a plan to a customer, adjusting negotiated prices, and initiating the subscription upon winning an opportunity represents a key action from Salesforce to Lago.
This enables sales teams to remain within Salesforce, their primary tool, and activate billing processes directly, without the need to switch platforms.
To assign a subscription and set prices in Lago directly from Salesforce, use the provided two flows via following Lago Flow templates.
#### Flow 1: `Lago Template - Create Lago SObject Records`
This Flow is used to create intermediate records in Lago Objects - `Lago Subscription`
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `Lago Template - Create Lago SObject Records`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers plan assignment when a Salesforce Account links to a Lago customer and the **opportunity status changes to closed-won**.
You can customize this flow to suit your specific needs. Moreover, you have the option to adjust the subscription fields and subscription charges fields being synchronized from Salesforce to Lago.
1. Create an opportunity by assigning an expected closed date and a stage;
2. Add a Lago plan to this opportunity **as a product** (Salesforce will automatically retrieve all plans from Lago in `Standard Price Book`);
3. Specify `1` for the quantity of the plan;
4. Use the custom UI to either assign this plan directly or to override prices; and
5. Click on 'Lago Override Plan' to finalize the subscription assignment.
By default, the lago subscription record in salesforce is created when the opportunity is `closed-won`. You can assign multiple subscriptions for the same opportunity.
#### Flow 2: `Lago Template - Create Subscription in Lago on Subscription Creation/Update`
This Flow is used to create subscriptions in Lago from Salesforce
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `Lago Template - Create Subscription in Lago on Subscription Creation/Update`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers plan assignment when `SyncToLago` checkbox is checked. You can customize this flow to suit your specific needs.
### Create subscriptions (lago native UI)
We also have option to create subscriptions in Lago directly from Salesforce using Lago's create subscription screen.
1. Log into your Salesforce instance;
2. Access the setup section via the settings gear icon in Salesforce;
3. Go to Object manager and find and open account object;
4. Go to page layout (or Lightning record page) depending on what you are using, and open the page layout in which you'd like to add the button to create subscription.
5. Add the button `Lago Subscription`
6. Save the page layout or lightning record page.
Open any account which has `lago_id` populated. Click on `Lago Subscription` button; it will pop-up Lago Screen (make sure you've entered correct `Front End URL` in Lago Base Configuration page); enter correct username and password. Save. A new subscription will be directly created in Lago. And, if Webhooks are configured correctly, it will also create `Lago Subscription` record in Salesforce.
We can add a new button ***Lago Subscription*** on *Account* page or *Opportunity* page
A new Lago Subscription record will be created via webhooks (if configured).
And after 1 minute another callout will be made to sync Charges.
### Terminate Subscription
We can terminate the subscription from Salesforce to lago only if the subscription is already synced to lago(status is *active* or *pending*).
Go to Lago Subscription record in Salesforce, and check `Terminate Subscription` checkbox.
As soon as `Terminate Subscription` is checked it will terminate the subscription in Lago. It is handled from the backend via trigger.
### Create one-off invoice
This enables sales team to create one-off invoice in lago from Salesforce.
Right from the opportunity record we add products which are related to `Lago Add-ons`, specify the quantity, description and amount.
To create one-off invoice and set prices in Lago directly from Salesforce, use the provided two flows via following Lago Flow templates.
#### Flow 1: [`Lago Template - Create Lago SObject Records`](/integrations/crm/salesforce-crm#flow-1-lago-template-create-lago-sobject-records)
The same flow as we created above to create subscription - is also used to create intermediate records in Lago Objects - `Lago Invoice`
#### Flow 2: `Lago Template - Generate Invoice in Lago On Lago Invoice Field Update`
This Flow is used to create one-off invoice in Lago from Salesforce
1. Log into your Salesforce instance;
2. Access the Setup section via the settings gear icon in Salesforce;
3. Find and select `Flows` under Process Automation in the sidebar;
4. Locate and open the `Lago Template - Generate Invoice in Lago On Lago Invoice Field Update`;
5. Click 'Save As' to create and save your own version of the template; and
6. Do not forget to click the `Activate` button to activate your flow.
The default setting triggers create invoice when `SyncToLago` checkbox is checked. You can customize this flow to suit your specific needs.
### Create one-off invoice (lago native UI)
We also have option to create one off invoice in Lago directly from Salesforce using Lago's create invoice screen.
1. Log into your Salesforce instance;
2. Access the setup section via the settings gear icon in Salesforce;
3. Go to Object manager and find and open Account object or Opportunity;
4. Go to page layout (or Lightning record page) depending on what you are using, and open the page layout in which you'd like to add the button to create Invoice.
5. Add the button `Lago Invoice`
6. Save the page layout or lightning record page.
Open any account which has `lago_id` populated. Click on `Lago Invoice` button; it will pop-up Lago Screen (make sure you've entered correct `Front End URL` in Lago Base Configuration page); enter correct username and password. Save. A new Invoice will be directly created in Lago. And, if Webhooks are configured correctly, it will also create `Lago Invoice` record in Salesforce.
We can add a new button ***Lago Invoice*** on *Account* page or *Opportunity* page
A new Lago Invoice record will be created via webhooks (if configured).
After 1 minute another callout will be made to sync invoice line items (add ons).
### Get Invoice pdf
Now we can also get invoice pdf directly directly from Salesforce.
1. Go to Lago Invoice
2. Open any Invoice which is already synced.
3. Click `Get Invoice pdf` > it will open PDF in a new tab.
## Debugging & logs
To ensure seamless data synchronization between Lago and Salesforce, every action and data transfer is meticulously logged.
These logs are accessible directly through the Lago package for comprehensive debugging and analysis:
1. Navigate to 'Lago Base Configuration': This is your starting point for accessing the debugging tools. and
2. Access Logs: Click on the 'Logs' tab to view a detailed record of all activities.
You can refresh logs to keep your data current or delete unnecessary logs to maintain clarity and efficiency in the debugging process.
This approach aids in promptly identifying and resolving integration issues.
# Airbyte (ETL)
Airbyte is an open-source **data integration platform** used as an ETL. With this integration, you can connect Lago billing data to any warehouses.
## Destinations
You can push Lago billing data to destinations such as Snowflake, BigQuery, Redshift, S3 buckets or Azure, for instance.
The entire list of data destinations enabled by Airbyte is listed on their [destinations documentation](https://docs.airbyte.com/category/destinations/).
## Data available for extraction
With Airbyte's native integration of Lago, you can push the following billing data to warehouses:
* billable\_metrics
* plans
* coupons
* add\_ons
* invoices
* customers
* subscriptions
At present this connector **only supports full refresh syncs** meaning that each time you use the connector it will sync all available records from scratch. Please use cautiously if you expect your API to have a lot of records.
Find the full documentation of [Airbyte's native Lago integration](https://docs.airbyte.com/integrations/sources/getlago/).
## 1. Connect Lago to Airbyte
First of all, you simply need to bring your Lago private API key.
In airbyte:
* Go to **Sources**;
* Select getLago as a source of data; and
* Paste your Lago private API key.
## 2. Select a destination
You can select any of the data destinations available in Airbyte. It could be a warehouse (BigQuery, Redshift, Snowflake...) or a file storage tool (S3, for instance). Please find here the entire list of [data destinations available in Airbyte](https://docs.airbyte.com/category/destinations/).
## 3. Sync billing data
In the following example, we connected Lago billing data to Snowflake data warehouse. Obviously, you can select another destination if needed.
1. Create a **data sync** between Lago source and your destination;
2. Define a **sync frequency**; and
3. Activate the sync in Airbyte between Lago source and your destination.
This action will populate Lago billing data into a warehouse (Snowflake in our example).
## 4. Query Lago billing data
Once the data has been populated in your destination, a warehouse in our example, you can easily query your billing data. Here is a query calculating your monthly revenue with Lago:
# Oso
[Oso](https://www.osohq.com/) is an authorization-as-a-service provider partnering with Lago to offer entitlements. You can use either the open-source version (available on [Github](https://github.com/osohq/oso)) or the cloud-hosted version. To create entitlements with Lago, you must open an account on Oso.
Oso offers a suitable solution for Entitlements. For more information, please refer to [Oso's documentation](https://www.osohq.com/docs/guides/model/entitlements).
## Define available features and plan's quota
First, define the available features for each plan. For instance, the Basic plan has a limited set of features, while the Premium plan offers the full range.
In addition to this, you can use Lago to bill metering and overage. This information can then be passed directly to Oso's `plan_quota` and `quota_used` to limit usage for a specific feature.
## Example
[Oso's documentation](https://www.osohq.com/docs/guides/model/entitlements) explains the following example of entitlements properly.
```ruby
actor User { }
resource Organization {
roles = ["admin", "member"];
permissions = ["create_repository"];
"member" if "admin";
}
resource Plan {
roles = ["subscriber"];
relations = { subscribed_organization: Organization };
"subscriber" if role on "subscribed_organization";
}
resource Feature {
relations = { plan: Plan };
}
declare plan_quota(Plan, Feature, Integer);
declare quota_used(Organization, Feature, Integer);
plan_quota(Plan{"pro"}, Feature{"repository"}, 10);
plan_quota(Plan{"basic"}, Feature{"repository"}, 0);
has_quota_remaining(org: Organization, feature: Feature) if
has_quota(org, feature, quota) and
quota_used(org, feature, used) and
used < quota;
has_quota(org: Organization, feature: Feature, quota: Integer) if
plan matches Plan and
has_relation(plan, "subscribed", org) and
plan_quota(plan, feature, quota);
has_permission(user: User, "create_repository", org: Organization) if
has_role(user, "member", org) and
has_quota_remaining(org, Feature{"repository"});
test "members can create repositorys if they have quota" {
setup {
quota_used(Organization{"apple"}, Feature{"repository"}, 5);
quota_used(Organization{"netflix"}, Feature{"repository"}, 10);
quota_used(Organization{"amazon"}, Feature{"repository"}, 0);
has_relation(Plan{"pro"}, "subscribed", Organization{"apple"});
has_relation(Plan{"pro"}, "subscribed", Organization{"netflix"});
has_relation(Plan{"basic"}, "subscribed", Organization{"amazon"});
has_role(User{"alice"}, "member", Organization{"apple"});
has_role(User{"bob"}, "member", Organization{"netflix"});
has_role(User{"charlie"}, "member", Organization{"amazon"});
}
assert has_quota_remaining(Organization{"apple"}, Feature{"repository"});
# Apple has quota remaining, so all good
assert allow(User{"alice"}, "create_repository", Organization{"apple"});
# Netflix has used all quota
assert_not allow(User{"bob"}, "create_repository", Organization{"netflix"});
# Amazon doesn't have any quota left
assert_not allow(User{"charlie"}, "create_repository", Organization{"amazon"});
}
```
# Introduction
Find all Lago native integrations with third party tools, whether it's related to payment providers, alerting systems or data integrations.
## Usage tracking integrations
}
href="/integrations/usage/segment"
>
Segment is used to track and ingest events that can be sent to Lago as
usage.
}
href="/integrations/usage/hightouch"
>
Reverse-ETL helping you sync data from any sources (database, warehouses,
spreadsheet...) to Lago.
## Payments integrations
}
href="/integrations/payments/gocardless-integration"
>
GoCardless is the global leader of direct debits bank payments.
}
href="/integrations/payments/stripe-integration"
>
Stripe is a suite of APIs powering online payment processing, especially
card payments.
}
href="/integrations/payments/adyen-integration"
>
Adyen is an omnichannel payment processing company providing multiple ways
to accept payments.
## Accounting integrations
{" "}
}
href="/integrations/accounting/netsuite"
>
NetSuite is the leading integrated cloud business software for business
accounting.
}
href="/integrations/accounting/xero"
>
Xero is a cloud-based accounting software for small businesses.
}
>
Quickbooks is a cloud-based accounting software for small businesses.
## Taxes integrations
{" "}
}
href="/integrations/taxes/lago-eu-taxes"
>
Lago now features an automatic European tax detection integration for your
customers.
}
href="/integrations/taxes/anrok"
>
Anrok is the global sales tax platform for software companies.
## CRM integrations
}
href="/integrations/crm/salesforce-crm"
>
Salesforce CRM integration is used to sync data from Lago to Salesforce.
}
href="/integrations/crm/salesforce-cpq"
>
Salesforce CPQ extension for Lago's native Salesforce package.
}
href="/integrations/crm/hubspot"
>
HubSpot CRM integration is used to sync data from Lago to HubSpot.
## Marketplaces & hyperscalers integrations
Lago integrates with marketplaces and hyperscalers through our partner
[Suger.io](https://suger.io).
}
href="/integrations/marketplaces/aws-marketplace"
>
Quickly list, transact, and co-sell on AWS Marketplace with Lago, via
Suger.io integration.
}
href="/integrations/marketplaces/azure-marketplace"
>
Quickly list, transact, and co-sell on Azure Marketplace with Lago, via
Suger.io integration.
}
href="/integrations/marketplaces/gcp-marketplace"
>
Quickly list, transact, and co-sell on GCP Marketplace with Lago, via
Suger.io integration.
## Alerting integrations
}
href="/integrations/alerting/zapier"
>
Use Zapier and Lago to trigger billing automations, such as an invoice
alerting system.
}
href="/integrations/alerting/n8n"
>
Use n8n and Lago to trigger billing automations, such as an overconsumption
alerting system.
## Data integrations
}
href="/integrations/data/airbyte"
>
Send billing data to any warehouses by using our integration with Airbyte
ETL services.
## Entitlements integrations
}
href="/integrations/entitlements/osohq"
>
Oso is an Authorization as service used for entitlements
# AWS Marketplace
Lago integrates with AWS marketplace through our partner Suger.io
If you're using Lago for metering and billing and looking to expand into AWS marketplace, [Suger](https://suger.io) is the ideal partner. Suger offers the fastest and easiest way to list, transact, and co-sell on AWS marketplace.
Their no-code, fully automated integration with Lago allows you to seamlessly track usage within your existing setup and allocate it across various cloud marketplaces.
This approach eliminates the need for migration or complex engineering, ensuring a smooth and hassle-free transition.
}
href="https://doc.suger.io/integrations/lago"
>
Quickly list, transact, and co-sell on AWS Marketplace with Lago, via Suger.io integration.
# Azure Marketplace
Lago integrates with Azure marketplace through our partner Suger.io
If you're using Lago for metering and billing and looking to expand into Azure marketplace, [Suger](https://suger.io) is the ideal partner. Suger offers the fastest and easiest way to list, transact, and co-sell on Azure marketplace.
Their no-code, fully automated integration with Lago allows you to seamlessly track usage within your existing setup and allocate it across various cloud marketplaces.
This approach eliminates the need for migration or complex engineering, ensuring a smooth and hassle-free transition.
}
href="https://doc.suger.io/integrations/lago"
>
Quickly list, transact, and co-sell on Azure Marketplace with Lago, via
Suger.io integration.
# GCP Marketplace
Lago integrates with GCP marketplace through our partner Suger.io
If you're using Lago for metering and billing and looking to expand into GCP marketplace, [Suger](https://suger.io) is the ideal partner. Suger offers the fastest and easiest way to list, transact, and co-sell on GCP marketplace.
Their no-code, fully automated integration with Lago allows you to seamlessly track usage within your existing setup and allocate it across various cloud marketplaces.
This approach eliminates the need for migration or complex engineering, ensuring a smooth and hassle-free transition.
}
href="https://doc.suger.io/integrations/lago"
>
Quickly list, transact, and co-sell on GCP Marketplace with Lago, via
Suger.io integration.
# Adyen
Lago's native integration with Adyen allows you to collect payments automatically when new invoices are generated.
Lago's seamless integration with Adyen offers a wide range of payment options, enabling you to conveniently collect payments from your customers. Supported payment methods include:
* Card payments (Visa, MasterCard, CB)
* Apple Pay
* Paypal
* American Express
* Amazon Pay
* Google Pay
And many more! With Lago's native Adyen integration, you can offer your customers a variety of payment options, enhancing their convenience and flexibility during transactions.
Please ensure that you have added payment methods to your Adyen account before setting up the integration ([see Adyen documentation](https://docs.adyen.com/payment-methods/add-payment-methods/)).
## Connecting Lago to Adyen
To set up the Adyen integration in Lago from our user interface, follow these steps:
1. In the side menu of your Lago app, navigate to **Settings**;
2. Select the **Integrations** tab;
3. Click **"Adyen"** to create a connection;
4. Give a name to this connection;
5. Assign a code for easy identification;
6. Enter the required connection fields (described in the next section); and
7. Click **Connect to Adyen** to confirm the integration.
## Adyen Connection Fields
When connecting Lago to Adyen, you need to provide information for the following fields.
The API Key is a mandatory field and can be found in your Adyen account. Follow these steps to retrieve the API Key:
* Go to your Adyen account and navigate to **Developers** > **API Credentials**;
* On the API Credentials page, create new credentials with a type of **Web service user**;
* Click on the **Create credentials** button to generate the API Key; and
* Copy the API Key and paste it in the corresponding field in Lago. Remember to save the changes.
The Merchant Account is required to ensure that Lago targets the correct Adyen account. To find the Merchant Account:
* Go to **Settings** > **Merchant accounts** in your Adyen account; and
* Copy the **Account code** of the targeted account you want to use with Lago.
The Live Prefix represents the prefix url of your live Adyen account. This field is optional. If left empty, you can connect a test account. However, for live accounts, you must provide a Live Prefix. Follow these steps to obtain the Live Prefix:
* Go to **Developers** > **API URLs** > **Prefix** in your Adyen account.
Adyen's HMAC signatures are used to protect webhook endpoints and messages created by Adyen. Lago requires this signature to properly decrypt outgoing webhooks from Adyen. To find the HMAC Signature:
* Create or edit a webhook in Adyen by accessing **Developers** > **Webhooks**;
* Choose a webhook, e.g. Standard webhook; and
* Under "Security" settings, you can find the HMAC Key.
The Live Prefix and HMAC Signature fields are optional and may not be required depending on your use case.
## Setting up Adyen's payments auto-capture
To enable automatic payment capture in your Adyen account, ensure that you have configured the account settings accordingly. Automatic payment capture allows for immediate processing without manual intervention. Refer to Adyen's documentation for instructions on [setting up auto capture](https://docs.adyen.com/online-payments/capture#automatic-capture).
## Turn on Adyen's recurring details
In Adyen, to enable recurring payments for a stored payment method, follow these steps:
1. Go to Developers > Additional Data;
2. Check the box for Recurring Details; and
3. Click Save.
## Setting up Adyen Webhook for listening to important events
**This step is crucial and mandatory** for Lago to receive and process messages from Adyen, enabling functionalities such as customer creation/update, payment processing, and refunds. To configure Adyen webhook and establish communication with Lago, follow the steps below:
1. Access your Adyen application and navigate to the **Developers** section;
2. Select **Webhooks** and create a new webhook of type **Standard**;
3. In the **Server configuration** section, locate the **General** settings; and
4. Copy and paste the following URL: **`https://api.getlago.com/webhooks/adyen/{{your_organization_id}}?code={{connection_code}}`**.
You can find your Organization ID in Lago under the Developers section in Lago, specifically in **API keys & ID** > **Organization ID**.
To find your **connection code**, navigate to the Integrations section in Lago and select the appropriate connection code for your Adyen integration.
**Please ensure that you complete this setup correctly, as your Adyen integration will not function without this vital step.**
## Setting Adyen as a Payment Provider for a customer
In order to facilitate automated payment collection, it is essential for the customer to exist in both the Lago and Adyen databases. Please note that in Adyen, customers are referred to as **Shoppers**.
### Adding a new customer in Adyen
If the customer does not already exist in Adyen, you can create them in Lago using either the user interface or the **[API](/api-reference/customers/create)**. When providing customer information, please ensure the following:
1. Set Adyen as the customer's **default payment provider**;
2. Select the Adyen connected account;
3. Keep the field associated with the **Adyen Payment Provider Customer ID** empty; and
4. **Enable** the option to automatically create the customer in Adyen.
Once the customer is added in Lago, they will be automatically synchronized with Adyen. Adyen will generate a unique Shopper ID, which will be stored in Lago. Typically, Adyen utilizes the Lago customer's **`external_id`** as the Shopper ID for seamless integration between the two platforms.
Upon successful customer creation, you will receive two **[webhook messages](/api-reference/webhooks/messages)** to keep you informed:
1. **`customer.checkout_url_generated`**: This message includes the checkout URL that provides access to the default payment method. It allows you to perform a pre-authorization payment and store the payment method securely; and
2. **`customer.payment_provider_created`**: This message confirms the successful creation of the customer in Adyen, indicating that the customer's details have been added to the Adyen database.
You may need to enable Developers -> Additional Data -> Payment -> Recurring details for the customer to be automatically created.
Please note that the customer will be created in Adyen only if the payment method has been stored through the checkout URL and pre-authorization payment.
### Using an existing customer from Adyen
If the customer and direct debit mandate already exist in Adyen, you can create the customer record in Lago using either the user interface or **[the API](/api-reference/customers/create)**. Follow these steps when adding customer information:
1. Set Adyen as the **default payment provider** for the customer in Lago;
2. Select the Adyen connected account;
3. Provide the **Adyen [Shopper Reference](https://docs.adyen.com/point-of-sale/card-acquisition/identifiers#:~:text=Shopper%20reference%3A%20a,contract%20payments.)** as the Lago **Payment provider customer ID**.
4. **Disable** the option to automatically create the customer in Adyen.
By following these steps, you can integrate an existing customer from Adyen into Lago, ensuring synchronization and consistency between the two platforms.
## Redirect url after checkout[](#checkout-redirect-url "Direct link to heading")
After establishing the connection with Adyen, set a success URL where your end customer will be directed after completing the checkout.
Please note that if it's not defined, your end customer will be redirected to Adyen's website.
Please note that you can edit or delete the redirect URL, and this will only affect new checkout URLs created.
URL defined should always begin with `http://` or `https://`.
## Adyen Checkout: storing customer's payment method information
When Lago automatically creates a customer in Adyen, you will receive a checkout link from Lago to facilitate the storage of your customer's payment method information.
The payload sent by Lago will have the following structure, with the checkout link stored under **`checkout_url`**:
```json
{
"webhook_type": "customer.checkout_url_generated",
"object_type": "payment_provider_customer_checkout_url",
"payment_provider_customer_checkout_url": {
"lago_customer_id": "88d23508-47fd-46bb-a87e-50c50f3cb371",
"external_customer_id": "hooli_1234",
"payment_provider": "adyen",
"payment_provider_code": "adyen_test",
"checkout_url": "https://test.adyen.link/PLEEA656869B11DF6B"
}
}
```
Note: The checkout link automatically expires after 69 days.
By utilizing this provided checkout link, your customers can perform a pre-authorization payment. It's important to note that the pre-authorization payment will not collect any funds from the customer. Once the pre-authorization is confirmed, Lago will send the payment method details and securely store them into Adyen for future transactions.
## Regenerate checkout link on demand
In cases where your end customer has not had the opportunity to complete the checkout process to inform their payment method
or wishes to modify the saved payment information, you can generate a new checkout link using the designated [endpoint](/api-reference/customers/psp-checkout-url).
```json
POST /api/v1/customers/:customer_external_id/checkout_url
```
Upon successful generation, the new checkout link will be available in the endpoint response, and it will not be delivered through a webhook message.
It is important to note that the new link will inherit the same expiration setting as the original one.
It is crucial to be aware that if a customer is not associated with any payment provider, the response will contain an error message.
## Creating payments from Lago Invoices
When a customer has Adyen defined as their payment provider, Lago seamlessly automates the process of triggering payments in Adyen whenever a new invoice is generated.
This integration ensures that payments are initiated in Adyen without any manual intervention. Lago's automatic payment creation saves time and effort, providing a streamlined experience for both you and your customers.
## Creating refunds from Lago Credit Notes
In cases where a customer has Adyen defined as their payment provider, Lago simplifies the refund process by automatically triggering refunds in Adyen whenever a new refund is initiated through credit notes.
This integration eliminates the need for manual refund processing and ensures that refunds are efficiently handled in Adyen. Lago's automated refund functionality helps you maintain accurate and timely refund transactions, enhancing customer satisfaction and operational efficiency.
## Payment disputes
In the event of a **lost** chargeback (dispute) within Adyen, Lago initiates an automatic response by marking the relevant invoice as disputed lost. This action involves populating the `dispute_lost_at` field with the timestamp when the dispute was lost. Following this update:
* The invoice becomes non-voidable;
* Generating a credit note is possible; however, refunding the payment back to the original payment method is not permitted; and
* The invoice cannot be resent for collection.
## Watch the demo video
# GoCardless
Lago's native integration with GoCardless allows you to collect payments via direct debit.
## Integration setup[](#integration-setup "Direct link to heading")
### Connect your GoCardless account[](#connect-your-gocardless-account "Direct link to heading")
To connect to GoCardless through the user interface:
1. In the side menu, select **"Settings"**;
2. Open the **"Integrations"** tab;
3. Click **"GoCardless"** to create a connection;
4. Give a name to this connection;
5. Assign a code for easy identification;
6. Click on **"Connect to GoCardless"** to be redirected to the GoCardless application;
7. Create a GoCardless account or log in to your existing account; and
8. Connect your account to be redirected to the Lago application.
When the OAuth connection is active, you will see the screen below, with your
secret key.
### Create webhook endpoints[](#create-webhook-endpoints "Direct link to heading")
To complete this process, you will need:
* Your Lago **organization ID**, available in the **"API keys & ID"** tab of the
**"Developers"** section; and
* Your **secret key**, available in the **"Integrations"** tab of the
**"Settings"** section ([learn more](#connect-your-gocardless-account)).
If you want Lago to automatically retrieve the status of the payments processed
via GoCardless, you must create a webhook endpoint in GoCardless. To do so:
1. Log in to your [GoCardless account](https://manage.gocardless.com/sign-in);
2. Go to the **"Developers"** section;
3. In the upper right corner, click **"Create"** and then select **"Webhook
endpoint"**;
4. Choose a name for this webhook (e.g. Lago);
5. Enter the following URL: `https://api.getlago.com/webhooks/gocardless/{{organization_id}}?code={{connection_code}}` (you must replace `organization_id` with your Lago organization ID, and the `connection_code` by the targeted Lago connection);
6. Enter your secret key; and
7. Click **"Create webhook endpoint"**.
In addition to this, you must create a webhook endpoint in Lago to retrieve the
checkout URL associated with each customer account
([learn more](#direct-debit)). To do so:
1. Go to the **"Developers"** section of the Lago application;
2. In the **"Webhooks"** tab, click **"Add a webhook"** on the right;
3. Enter your webhook URL; and
4. Click **"Add webhook"** to confirm.
For more information about our webhooks, please refer to the
[API documentation](/api-reference/webhooks/format---signature).
## Redirect url after checkout[](#checkout-redirect-url "Direct link to heading")
After establishing the connection with GoCardless, set a success URL where your end customer will be directed after completing the checkout.
Please note that if it's not defined, your end customer will be redirected to GoCardless’s website.
Please note that you can edit or delete the redirect URL, and this will only affect new checkout URLs created.
URL defined should always begin with `http://` or `https://`.
## Customer information[](#customer-information "Direct link to heading")
To collect payments automatically, the customer must exist in both the Lago and
GoCardless databases.
### New customer[](#new-customer "Direct link to heading")
If the customer does not already exist in GoCardless, you can first create them
in Lago, either via the user interface or
[the API](/api-reference/customers/create). When adding customer information, you
must:
1. Provide the customer's email address;
2. Define GoCardless as the **default payment provider**;
3. Select the GoCardless connected account;
4. Leave the field associated with the **GoCardless customer ID** blank; and
5. **Enable** the option to automatically create the customer in GoCardless.
The customer will automatically be added to GoCardless. GoCardless will then
return the customer ID, which will be stored in Lago.
When the customer is successfully created, you will receive two
[webhook messages](/api-reference/webhooks/messages):
* `customer.payment_provider_created` that confirms the creation of the customer
in GoCardless; and
* `customer.checkout_url_generated` that includes the checkout URL to set up the
direct debit ([learn more](#direct-debit)).
### Existing customer[](#existing-customer "Direct link to heading")
If the customer and direct debit mandate already exist in GoCardless, then you
should create the customer record in Lago, either via the user interface or
[the API](/api-reference/customers/create). When adding customer information, you
must:
1. Provide the customer's email address;
2. Define GoCardless as the **default payment provider**;
3. Select the GoCardless connected account;
4. Provide the **GoCardless customer ID**; and
5. **Disable** the option to automatically create the customer in GoCardless.
## Direct debit[](#direct-debit "Direct link to heading")
To collect payments via direct debit, a mandate must be created. To do so:
1. Retrieve the checkout URL included in the `customer.checkout_url_generated`
webhook; and
2. Redirect your customer to the checkout page, so that they can complete the
online form and approve the mandate.
The mandate must be validated by GoCardless before the first payment can be
processed. It can take up to six business days to validate a new mandate. For
more information about payment timings, please consult the
[GoCardless FAQ](https://gocardless.com/faq/merchants/direct-debit/).
To collect payments via direct debit, the currency of the mandate must match
the currency of the plan associated with the customer's subscription.
Each time a new invoice with an **amount greater than zero** is generated by
Lago, a payment will automatically be created. GoCardless will record the
invoice ID and process the payment. Payments via direct debit are usually
processed within five business days. If the payment is successful, the status of
the payment will switch from `pending` to `succeeded`.
If the payment fails, the status of the payment will switch from `pending` to
`failed` and Lago will generate an `invoice.payment_failure`
[webhook](/api-reference/webhooks/messages).
If you have signed up for [GoCardless
Success+](https://gocardless.com/solutions/success-plus/), failed payments may
be automatically resubmitted, in which case Lago will automatically update the
invoice payment status.
## Regenerate checkout link on demand
In cases where your end customer has not had the opportunity to complete the checkout process to inform their payment method
or wishes to modify the saved payment information, you can generate a new checkout link using the designated [endpoint](/api-reference/customers/psp-checkout-url).
```json
POST /api/v1/customers/:customer_external_id/checkout_url
```
Upon successful generation, the new checkout link will be available in the endpoint response, and it will not be delivered through a webhook message.
It is important to note that the new link will inherit the same expiration setting as the original one.
It is crucial to be aware that if a customer is not associated with any payment provider, the response will contain an error message.
# Stripe
Lago's native integration with Stripe allows you to collect payments automatically when new invoices are generated.
## Watch the demo video
## Integration setup[](#integration-setup "Direct link to heading")
To set up the integration with Stripe through the user interface:
1. In the side menu, select **"Settings"**;
2. Select the **"Integrations"** tab;
3. Click **"Stripe"** and add a new connection;
4. Give this new connection a name and a code;
5. Enter your Stripe API key ([locate your API key](https://support.stripe.com/questions/locate-api-keys-in-the-dashboard)); and
6. Click **"Connect to Stripe"** to confirm.
By default, customers created in Lago are not automatically created in Stripe.
If you want your Lago customers to be added to Stripe, you need to activate
this option ([learn more](#new-customer)).
## Redirect url after checkout[](#checkout-redirect-url "Direct link to heading")
After establishing the connection with Stripe, set a success URL where your end customer will be directed after completing the checkout.
Please note that if it's not defined, your end customer will be redirected to Stripe's website.
Please note that you can edit or delete the redirect URL, and this will only affect new checkout URLs created.
URL defined should always begin with `http://` or `https://`.
## Customer information[](#customer-information "Direct link to heading")
To collect payments automatically, the customer must exist in both the Lago and
Stripe databases.
### New customer[](#new-customer "Direct link to heading")
If the customer does not already exist in Stripe, you can first create them in
Lago, either via the user interface or [the API](/api-reference/customers/create).
When adding customer information, you must:
1. Define Stripe as the **default payment provider**;
2. Leave the field associated with the **Stripe customer ID** blank;
3. **Enable** the option to automatically create the customer in Stripe; and
4. Define payment method options for this customer. Possible values are `card`, `link`, `sepa_debit`, `us_bank_account` and `bacs_debit`.
The customer will automatically be added to Stripe. Stripe will then return the
customer ID, which will be stored in Lago.
### Existing customer[](#existing-customer "Direct link to heading")
If the customer already exists in Stripe but not in Lago, you should create the
customer record, either via the user interface or
[the API](/api-reference/customers/create). When adding customer
information, you must:
1. Define Stripe as the **default payment provider**;
2. Provide the **Stripe customer ID**;
3. **Disable** the option to automatically create the customer in Stripe; and
4. Define payment method options for this customer. Possible values are `card`, `link`, `sepa_debit`, `us_bank_account` and `bacs_debit`.
## Supported payment methods
Lago's Stripe integration accommodates a variety of payment methods, both generic and region-specific.
The checkout URL provided by Lago is designed to handle multiple payment options seamlessly.
Lago's Stripe integration includes a universal card payment method that supports various currencies, ideal for global transactions.
This method is set as the default to facilitate recurring payments, ensuring Lago can process charges for your customers efficiently.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["card"]
}
}
}'
```
For European customers, Lago supports Stripe SEPA Debit (Single Euro Payments Area).
Accepting a mandate through this method authorizes you to debit your customers' accounts for recurring payments via Lago.
The designated payment method for SEPA transactions within Lago is identified as `sepa_debit`.
It's important to note that **this payment option is exclusive to invoices in `EUR` currency**.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["sepa_debit"]
}
}
}'
```
For US-based transactions, Lago integrates Stripe ACH Debit, leveraging the Automated Clearing House for electronic bank-to-bank payments.
Upon accepting a mandate, you gain authorization to execute recurring debits from your customers' accounts through Lago.
The designated payment method for ACH transactions within Lago is identified as `us_bank_account`.
It's important to note that **this payment option is exclusive to invoices in `USD` currency**.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["us_bank_account"]
}
}
}'
```
For UK transactions, Lago integrates Stripe BACS Debit, utilizing the UK's BACS system for direct bank-to-bank payments.
By accepting a mandate with this method, you're authorized to initiate recurring debits from your customers' accounts through Lago.
The specific payment method for BACS transactions within Lago is designated as `bacs_debit`.
It's important to note that **this payment method is exclusively for invoices in `GBP` currency.**
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["bacs_debit"]
}
}
}'
```
For card transactions, you can enable the [Link](https://stripe.com/payments/link) feature to offer one-click payments.
Link automatically fills in your customers' payment information, ensuring a seamless and secure checkout experience.
If you are using the `link` feature, it must be used in conjunction with `card`.
```bash
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/customers" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"customer": {
"external_id": "5eb02857-a71e-4ea2-bcf9-57d3a41bc6ba",
"address_line1": "5230 Penfield Ave",
"billing_configuration": {
"invoice_grace_period": 3,
"payment_provider": "stripe",
"provider_customer_id": "cus_12345",
"sync": true,
"sync_with_provider": true,
"provider_payment_methods": ["card", "link"]
}
}
}'
```
## Stripe Checkout: storing customer's payment method information
Checkout page shows only selected payment methods for customers.
When Lago automatically creates a customer in Stripe, you will receive a checkout link from Lago to facilitate the storage of your customer's payment method information.
The payload sent by Lago will have the following structure, with the checkout link stored under `checkout_url`:
```json
{
"webhook_type": "customer.checkout_url_generated",
"object_type": "payment_provider_customer_checkout_url",
"payment_provider_customer_checkout_url": {
"lago_customer_id": "88d23508-47fd-46bb-a87e-50c50f3cb371",
"external_customer_id": "hooli_1234",
"payment_provider": "stripe",
"checkout_url": "https://checkout.stripe.com/c/pay/prod_c15sTbBMLep5FKOA9b9pZBiRBBYYSU1IJ5T89I5TTtpKgzE380JSmxnVYz#fidkdWxOYHw"
}
}
```
Note: The checkout link automatically expires after 24 hours!
By utilizing this provided checkout link, your customers can perform a pre-authorization payment. It's important to note that the pre-authorization payment will not collect any funds from the customer. Once the pre-authorization is confirmed, Lago will send the payment method details and securely store them into Stripe for future transactions.
## Regenerate checkout link on demand
In cases where your end customer has not had the opportunity to complete the checkout process to inform their payment method
or wishes to modify the saved payment information, you can generate a new checkout link using the designated [endpoint](/api-reference/customers/psp-checkout-url).
```bash
POST /api/v1/customers/:customer_external_id/checkout_url
```
Upon successful generation, the new checkout link will be available in the endpoint response, and it will not be delivered through a webhook message.
It is important to note that the new link will inherit the same expiration setting as the original one.
It is crucial to be aware that if a customer is not associated with any payment provider, the response will contain an error message.
## Default payment method
When you add a new payment method in Stripe, **Lago automatically sets it as the default**.
This guarantees that Lago uses the latest payment method for a customer. However, if you manually designate one of
multiple payment methods as the default, Lago will use it for payments instead the most recent one.
## Payment intents[](#payment-intents "Direct link to heading")
Once Stripe is connected and the customer exists in both databases, you can
start collecting payments.
### Succeeded payments
Each time a new invoice with an **amount greater than zero** is generated by
Lago, a payment intent will automatically be created. Stripe will record the
invoice ID and process the payment. If the payment is successful, the status of
the payment will switch from `pending` to `succeeded`.
### Failed payments
If the payment fails, the status of the payment will switch from `pending` to
`failed` and Lago will generate an `invoice.payment_failure`
[webhook](/api-reference/webhooks/messages).
### Payments requiring validation
When a payment requires multi-step authentication, such as 3D Secure (3DS), Lago triggers a `payment.requires_action` [webhook](/api-reference/webhooks/messages#payment-requires-action).
This webhook provides the URL for completing the 3DS process. It's important to note that **most payments in India require 3DS authentication** due to [RBI regulations](https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=12051\&Mode=0).
### Minimum payment amount
If the new invoice amount falls below the [minimum amount supported by Stripe](https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts), the payment status will remain as `pending`.
A valid payment method for the customer must be defined in Stripe for the
payment intent to succeed ([learn how to save payment
details](https://stripe.com/docs/payments/save-and-reuse)).
## Payment disputes
In the event of a **lost** payment dispute within Stripe, Lago initiates an automatic response by marking the relevant invoice as disputed lost. This action involves populating the `dispute_lost_at` field with the timestamp when the dispute was lost. Following this update:
* The invoice becomes non-voidable;
* Generating a credit note is possible; however, refunding the payment back to the original payment method is not permitted; and
* The invoice cannot be resent for collection.
# Anrok
Lago's native integration with Anrok allows you to automatically update your invoices with tax amounts sourced directly from Anrok. This integration ensures compliance with international tax regulations by calculating taxes for US & non-US obligations, like VAT.
**PREMIUM FEATURE** ✨
This feature is only available to users with a premium license. Please
**[contact us](mailto:hello@getlago.com)** to get access to Lago Cloud and Lago
Self-Hosted Premium.
## Overview
Lago’s integration with Anrok simplifies tax calculation and reporting by syncing invoice amounts with Anrok for filing.
When an invoice is in draft status, Lago generates an ephemeral transaction in Anrok to calculate the preliminary taxes. Once the invoice is finalized, Lago creates a permanent transaction in Anrok to calculate the final taxes, marking it for reporting to the appropriate tax authority via Anrok.
To calculate the appropriate tax for each line item, Lago sends the customer’s address, tax identifier (if applicable), and the relevant product ID to Anrok. Anrok then calculates the tax for the invoice and returns the data to Lago, which is used to update the invoice with accurate tax information. Additionally, Lago synchronizes updates for voided and disputed invoices, as well as any credit notes created, ensuring that your records remain up to date.
## Prerequisites
1. **Premium feature**: To access Anrok via Lago, you’ll need to be under the Premium license.
2. **Getting Started**: We recommend reviewing the [Anrok Getting Started Guide](https://help-center.anrok.com/hc/en-us/categories/4410165176339-Getting-Started-Guide) before initiating the setup process.
3. **Anrok Account**: Ensure you have an Anrok account. Ideally, test the connection via an Anrok sandbox account to your Lago test account. Contact the Anrok team to request a free sandbox account.
4. **Physical Nexus**: Make sure you are correctly recording physical nexus in Anrok. Add or manage your physical nexus through the "Jurisdictions" tab by clicking the “Manage Physical Nexus” button.
5. **Products in Anrok**: Create products in Anrok, assigning a tax configuration to each product you sell in Lago. You will need the IDs of these products when setting up the Anrok integration in Lago (see the mapping below).
6. **Customer Exemptions in Anrok**: If necessary, upload valid exemption certificates for your customers in Anrok. Ensure that when you create a customer profile in Lago, you use the same customer ID as in Anrok. This consistency allows Lago to correctly identify the customer and apply the exemption certificates when calculating taxes.
## Connect Anrok to Lago
Lago allows you to connect your different Anrok instances. For example, you could connect both a sandbox and a production Anrok account. To do so:
1. In Lago, please go to Settings > Integration
2. Click on Anrok
3. Define a name and code for this connection; and
4. Enter your Anrok API key
### Mapping items between Lago and Anrok (mandatory)
To synchronize invoices and retrieve tax data, Lago needs to establish a one-to-one relationship between its objects and Anrok products. Follow these steps to map an item:
1. In Anrok, navigate to the **Products IDs** section.
2. Click on a product and **copy its Product ID.**
3. In Lago, navigate to **Integration** > **Anrok** > **Mapping**.
4. Choose the item you want to associate with the Product ID selected in step 2.
5. **Paste the Product ID to map the item** — repeat this action for all items in Lago that require mapping.
The invoice will be marked as `failed` if any item requiring tax calculation from Anrok is not properly mapped and no fallback item is provided.
### Mapping a fallback item (mandatory)
The fallback item serves as a backup and is used if the mapping of other items is not defined. This dummy item ensures continuous data synchronization between Lago and Anrok in the event of mapping issues.
## Customer configuration for tax calculation
### Customer synchronization
When creating or updating a Lago customer, you can choose to link it to an existing Anrok customer.
The first option is to **automatically create a new customer from Lago to Anrok**. Follow these steps:
1. Create or update a new Lago customer;
2. Select the targeted Anrok connection;
3. Check the box labeled ‘Create this customer automatically in Anrok’; and
4. Save and create this new customer.
If the customer is successfully created in Anrok, a new field will be displayed in the Lago customer view, providing a direct link to the corresponding Anrok customer.
The second option is to **import an existing Anrok customer to a Lago customer**. Follow these steps:
1. Create or update a Lago customer;
2. Select the targeted Anrok connection;
3. Ensure the box labeled ‘Create this customer automatically in NetSuite’ is unchecked;
4. Paste the Anrok customer ID in the appropriate field; and
5. Save and create this new customer.
If the customer is successfully synced in Anrok, a new field will be displayed in the Lago customer view, providing a direct link to the corresponding Anrok customer.
Please note that in both cases, the customer will be created in Anrok after the first invoice is synchronized.
### Address requirements
Anrok requires that each customer in Lago has a valid shipping address. If a shipping address is not available, Lago will default to using the billing address for tax calculation purposes. If both addresses are invalid or missing, Lago will be unable to generate the invoice, and the invoice status will be marked as failed. In such cases, you will be notified of the failure in the dashboard and via webhook.
### Tax identifier
If a customer has a `tax_identification_number` configured in Lago, this ID will be sent to Anrok for tax calculation and reporting. This ID is essential for determining whether the transaction is subject to a reverse charge in eligible VAT countries.
### Tax exempt customers
For customers who qualify for tax exemptions, you need to create a Certificate in your Anrok dashboard. Ensure that the customer profile in Lago uses the same customer ID as in Anrok in the Anrok customer ID. This consistency allows Lago to correctly identify the customer and apply the exemption certificates when calculating taxes.
## Current usage
Lago queries Anrok for the current usage and wallet ongoing balance. To ensure the best experience, Lago caches the results of current usage taxes for 24 hours.
## Error management
### Refresh draft invoice with tax errors
When an invoice is in `draft` and encounters a tax synchronization error, you have the option to refresh the invoice to recalculate the tax. The invoice remains editable during this process, and the error will not prevent the invoice from being `finalized`. However, if the error persists after attempting to finalize the invoice, the invoice will be marked as `failed`.
### Retry synchronization for failed invoice
When an invoice fails due to a tax synchronization error, you have the option to manually re-sync each invoice individually from the invoice details page or via this [endpoint](/api-reference/invoices/retry_finalization). Alternatively, you can go to the integration settings and trigger a bulk invoice synchronization.
### Retry synchronization for voided / disputed invoices
When an invoice is voided or disputed, Lago will sync this updated record with Anrok to ensure your reports are accurate. If the sync fails, you will be notified via webhook. In that case, please manually resync the voided or disputed invoice through the dashboard.
### Retry synchronization for credit notes
When a credit note is created, Lago will sync this record with Anrok to ensure your reports are accurate. If the sync fails, you will be notified via webhook. In that case, please manually resync the credit note through the dashboard.
### Pay in advance non invoiceable charge
Lago will notify you via webhook if a tax error occurs when a non-invoiceable fee paid in advance is generated. The fee will not be created. Please note that you will need to fix the issue and resend the event to generate the fee. For any assistance, please contact the Lago team.
### Tax error scenario
If Lago is unable to generate an invoice or sync it to Anrok, you will be alerted via the dashboard and webhook.
Tax synchronization and invoice generation can fail due to the following reasons:
1. Incorrect connection settings (API key).
2. Items used in objects or fallback items not mapped.
3. Missing customer shipping or billing address.
4. Timeout or internal service error.
Tax synchronization can fail during the following processes:
1. Calculating taxes in one-off-invoice form
2. Refreshing a draft invoice
3. Finalizing an invoice
4. Generating a fee paid in advance non-invoiceable
5. Fetching current usage
6. Voiding an invoice
7. Disputing an invoice
8. Creating a credit note
If an issue arises, please check the mapping, verify the customer address and launch a synchronization; or contact the Lago team for assistance.
# Lago EU Taxes
Lago now features an automatic European tax detection integration for your customers.
## Enable Lago's EU Tax integration
Activate Lago's automatic EU tax detection in just a few steps:
1. Navigate to your Lago instance **Settings**;
2. Select the **'Lago EU Tax Management'** integration;
3. Enter or confirm your organization's country; and
4. Hit **'Connect'** to activate this integration.
## Automated EU tax rates detection
When you connect the Lago EU Tax Management integration, it automatically generates a list of standard European tax rates.
These rates, labeled as `automated` in Lago, are synchronized with the latest standard tax rates for European countries,
ensuring your tax calculations are always up-to-date and compliant.
Each tax rate begins with the `lago_` prefix, ensuring a uniform and easily identifiable format across your tax rate list.
This systematic approach simplifies the management and recognition of these automated tax entries within your system.
## Auto-application of taxes: decision tree
Lago's initial step in the automated tax application involves verifying if a customer has a `tax_identification_number`.
This check occurs whenever a customer's profile is created or updated, ensuring that the most current tax-related information
is used in subsequent processes.
### B2B tax decision process
When a `tax_identification_number` is identified on a customer profile, Lago conducts a real-time verification
using the [EU's VAT Information Exchange System (VIES)](https://ec.europa.eu/taxation_customs/vies/#/vat-validation) to
confirm the existence of the company.
**In case the VIES check matches a valid company:**
1. If the customer's company is registered in the same country as your organization, Lago applies the customer
country's tax rate;
2. If the customer's company is registered in the same country as your organization, but there is a tax exception for a particular zipcode, Lago applies the tax exception of this specific zipcode; or
3. If the customer's company is registered in a different country than your organization, Lago implements a
**reverse charge** mechanism, applying a 0% tax rate.
### B2C tax decision process
If the VIES check does not confirm an active company or if no `tax_identification_number` is provided,
Lago then assesses the `country` associated with your customer. Based on this:
1. If your customer's `country` is unspecified, Lago defaults to applying your organization's country tax rate; or
2. If your customer's `country` is within the European Union, Lago applies the tax rate corresponding your customer's EU country; or
3. If your customer's `country` is outside the European Union, Lago applies a **tax exempt** rate at 0%.
## Guidelines for VIES checks by Lago
Lago performs VIES verifications under these circumstances:
* The Lago EU Tax Management integration is activated;
* A customer profile is either created or updated. Changes in customer details could influence their applicable tax rates;
* Zipcodes are important to define tax exceptions. Make sure to define them for all your customers; and
* When a new tax rate is identified for a customer, Lago automatically updates the customer's profile by replacing the old tax rate with the new one.
## Logging VIES verifications
Lago ensures transparency and compliance by logging each VIES check. This occurs whenever you create or update a customer.
For each check, Lago dispatches a webhook message. This allows you to record these validations for compliance purposes.
You can access and review any of these automated checks as needed.
# Hightouch
Hightouch is a Data Activation platform that syncs data from sources (database, warehouses, spreadsheet and much more) to business applications and developer tools. This data can be sent to Lago, our usage-based billing platform, to automate your billing process and ensure accurate invoicing for your customers.
Here's a step-by-step guide to help you get started:
## Prerequisites
**In Lago:**
1. Create a Lago organization to manage your billing and invoicing;
2. Create a Billable metric to track the usage of your customers;
3. Create a Plan and price the above billable metric to determine the billing rates for your customers; and
4. Create a Customer and assign the Plan.
**In Hightouch:**
1. Create a Hightouch account;
2. Create a data source (ideally, product usage of your customer);
3. Create a **HTTP Request** destination.
## Send usage from Hightouch to Lago
### Create a data source
To accomplish this, you'll need first to create a source in Hightouch. This can be done by following these simple steps:
1. Navigate to the **Sources** tab;
2. Add a **new source**; and
3. Choose and set up a data source that is available in Hightouch (it could be a database, a warehouse or a spreadsheet, for instance).
### Use the HTTP Request destination
Lago uses Hightouch's HTTP Request to ingest usage. Here is how to set it up:
1. Go to the **Destinations** tab;
2. Select the **HTTP Request** destination;
3. Define your **Headers**. Lago requires `Authorization` (secret, used for the API Key) and `Content-Type: application/json` headers; and
4. Save this newly created destination.
### Create a Sync
In order to send usage from Hightouch to Lago, you will have to create a new **Sync**. To do so, go in the **Syncs** tab and create a new sync from a source to this HTTP Request destination.
1. Configure when you want to trigger the event (row added, row deleted, row updated);
2. Define `POST` as the targeted HTTP Method;
3. Define the targeted url (for usage events, use `https://api.getlago.com/api/v1/events`);
4. Send data as `JSON` and use the JSON editor;
5. Define rate limits, if applicable
### Example of JSON payload
You can define manually the JSON payload that will be sent to Lago. Note that Hightouch supports Liquid template language to insert variables from your source to your JSON payload. These variables are created following this syntax: `"{{ row.variable }}"`, *"variable"* being the column name of your source.
Here is a JSON payload example to send usage events to Lago:
```json
{
"event": {
"transaction_id": "{{ row.transactionId }}",
"external_customer_id": "{{ row.customerId }}",
"code": "invoice_created",
"properties": {
"invoice_id": "{{ row.invoiceId }}"
}
}
}
```
The `body` structure of the event depends on your use case. Please adapt it if needed (*ie: remove or add properties*).
### Test and activate your sync
Note that you can test your sync with a data sample. As a result of this test, you should see data flowing into Lago, in the events list. Once you are ready to go, you can activate this sync, and define the periodic trigger.
## Hightouch to Lago - demo video
If easier, please find a demo video explaining the full setup to send events from Hightouch to Lago.
# Segment
Segment is a powerful tool that allows you to track the usage of your customers, providing valuable insights that can help you make data-driven decisions. This data can be sent to Lago, our usage-based billing platform, to automate your billing process and ensure accurate invoicing for your customers.
Here's a step-by-step guide to help you get started:
## Prerequisites
**In Lago:**
1. Create a Lago organization to manage your billing and invoicing;
2. Create a Billable metric to track the usage of your customers;
3. Create a Plan and price the above billable metric to determine the billing rates for your customers; and
4. Create a Customer and assign the Plan.
**In Segment:**
1. Create a Segment account;
2. Create a data source (ideally, product usage of your customer);
## Send usage from Segment to Lago
### Create a function
To accomplish this, you'll need to create a custom **Function** in Segment. This can be done by following these simple steps:
1. Navigate to the **Catalog** in Segment;
2. Click the **Functions** tab to access the custom Functions feature;
3. Choose to create your first function and follow the prompts to set it up.
### Use the Destination function
Make sure to select the **Destination function**, as you want to send data from Segment to Lago.
### Post Request to Lago events
To successfully integrate Lago with Segment, you'll need to replace the pre-written functions in the code editor with the following code. This example function, written by the Lago team, will catch a **Track** event from Segment, define the targeted endpoint (events) in Lago, build the body of the request, and finally post the event.
```javascript
// Running everytime a Track call is made on Segment
async function onTrack(event, settings) {
// events endpoint to reach
const endpoint = 'https://api.getlago.com/api/v1/events';
// body of the event following Lago documentation
const body = {
event: {
transactionId: event.messageId,
externalCustomerId: event.userId,
code: event.event,
properties: {
invoiceId: event.properties.invoice_id
}
}
};
// Post event
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Authorization': `Bearer ${settings.api}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
return response.json();
}
```
This function can be adapted with Identify, Group or Page events. Please, refer to [Segment's documentation](https://segment.com/docs/connections/functions/destination-functions/) for all available actions.
The `body` structure of the event depends on your use case. Please adapt it if needed (*ie: remove or add properties*). You can also add conditions if you want to send data to Lago only on specific events.
### Use the test mode editor
By using a sample event, you can preview the incoming data fetched from a Segment event. This will help you post a request for existing data or debug.
### Hide sensitive data
Let's take back the example from the code written above. We decided to hide the **API Key** and mark it as sensitive information. By setting this as a variable, you make sure not to hard code your private key in the function.
To create **Settings** variables:
1. Go to the **Settings** tab;
2. **Add** a new Setting;
3. Define a **Name** and a **Label** for this Settings;
4. Define it as **Required** or **Optional**; and
5. Mark is as **Sensitive** or not.
### Send usage events to Lago
By running the function in Segment, this will send a test usage to Lago events. You can retrieve this event in the events list. By finalizing the setup in Segment, the function will be automatically triggered based on your defined behavior
## Segment to Lago - demo video
If easier, please find a demo video explaining the full setup of custom functions to send event from Segment.com to Lago.
# Clone Segment pricing
Replicate Segment's hybrid pricing model with Lago.
Build a hybrid pricing and billing system like [Segment](https://segment.com/), the Customer Data Platform leader, based on subscription plans, with a usage-based component that makes your revenue grow with your users.
## Summary
Meter unique users with a billable metric by using the `unique_count_agg` aggregation type.
[(More here)](#step-1-keep-track-of-unique-users).
Create a new price plan with tiers of tracked users, using the graduated pricing model.
[(More here)](#step-2-create-a-plan-with-tiers).
Ingest raw usage of users that are automatically deduplicated by Lago.
[(More here)](#step-3-ingest-meter-for-unique-users-in-real-time).
## Pricing structure
Segment offers three pricing plans, called 'Free', 'Team' and 'Business'. As the latter has a custom pricing, we will focus on the first two plans.
| Plan | Free plan | Team plan |
| --------------------------- | ---------- | ----------------- |
| Subscription Fee | \$0/month | \$120/month |
| Base Consumption (included) | 1,000 MTUs | 10,000 MTUs |
| Consumption (10k-25k MTUs) | n/a | \$0.012/month/MTU |
| Consumption (25k-100k MTUs) | n/a | \$0.011/month/MTU |
| Consumption (100k+ MTUs) | n/a | \$0.010/month/MTU |
| Trial Period | n/a | 14 days |
The usage-based component in Segment's pricing is related to **monthly tracked users (MTUs)**, namely the number of unique users whose data is stored on the platform each month.
As these are **unique users**, we must ensure that each user is counted only once during the billing process.
Now let's see how we can implement Segment's pricing plans using Lago.
## Step 1: Keep track of unique users
Segment has implemented a graduated pricing model, based on the number of MTUs.
| MTUs | Price |
| ------------- | ------------ |
| 10k-25k MTUs | \$0.012/unit |
| 25k-100k MTUs | \$0.011/unit |
| 100k+ MTUs | \$0.010/unit |
Therefore, we need to calculate the number of unique users in order to implement our second pricing plan.
We are going to use a billable metric, which will allow us to aggregate incoming events on the platform to measure consumption.
We have created a billable metric, called **Monthly Tracked Users**, which includes the **`user_id` property**. In addition to this, we have defined `unique_count_agg` as the aggregation type.
What does this mean? Every time the customer data platform (e.g. Segment) records a new activity, a `mtu` event will be sent to Lago, which will then use the `user_id` property to deduplicate users to get only the total number of unique ones.
```bash Create a metric tracking unique users
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Monthly Tracked Users",
"code": "mtu",
"aggregation_type": "unique_count_agg",
"weighted_interval": null,
"recurring": false,
"field_name": "user_id",
"filters": []
}
}'
```
## Step 2: Create a plan with tiers
It’s time to create our **Team plan**. The subscription part is similar to the 'Free plan' (except that the amount is now \$120). We can also add the 14-day free trial currently offered by Segment.
To charge customers for consumption (i.e. based on MTUs), we need to add a charge to our plan.
Using the `mtu` billable metric created previously, we have implemented the graduated pricing model to reproduce Segment's pricing, including 10,000 free units (i.e. 10,000 unique users).
Following this example, for a customer on the ‘Team’ plan with 30,000 MTUs, at the end of the month, their invoice will amount to:
* \$120 (first 10,000 MTUs)
* \$180 (next 15,000 MTUs)
* \$55 (last 5,000 MTUs)
Our pricing plan is now ready!
```bash Create a plan with tiers of MTUs
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Team",
"code": "team",
"interval": "monthly",
"amount_cents": 12000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"charges": [
{
"billable_metric_id": "f8e854e5-69a3-420f-88a2-296324ee17d0",
"invoice_display_name": null,
"billable_metric_code": "mtu",
"created_at": "2024-05-03T22:32:09Z",
"charge_model": "graduated",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"graduated_ranges": [
{
"to_value": 10000,
"from_value": 0,
"flat_amount": "0",
"per_unit_amount": "0"
},
{
"to_value": 20000,
"from_value": 10001,
"flat_amount": "0",
"per_unit_amount": "0.012"
},
{
"to_value": null,
"from_value": 20001,
"flat_amount": "0",
"per_unit_amount": "0.011"
}
]
},
"filters": [],
"taxes": []
}
],
"taxes": []
}
}'
```
## Step 3: Ingest usage for unique users in real-time
For every user accessing Segment's platform, an event is dispatched containing the `user_id` property. Lago seamlessly handles deduplication to ensure accurate tracking of unique users.
```bash Ingest event for each transaction
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "{{$randomUUID}}",
"code": "mtu",
"external_customer_id": "hooli_1234",
"properties": {
"user_id": "user_id_001"
}
}
}'
```
## Wrap-up
Hybrid pricing plans are very popular among SaaS, API, fintech and data companies like Segment.
With Lago, you can easily adapt this template to create your own hybrid pricing plan, using some of our most popular features:
* **Plan models**, including monthly/yearly plans that can be paid in advance or in arrears;
* **Billable metrics**, including multiple aggregation types; and
* **Charges**, including our graduated pricing model (and more).
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Introduction
Replicate these popular B2B pricing templates to kickstart your journey with Lago.
Whether you are an API company, a fintech scale-up, an established SaaS provider or an early-stage data platform, find the pricing template that meets your needs and discover how Lago can help you implement it.
## Per-token pricing (AI)
}
href="/templates/per-token/mistral"
>
Build a transparent per-token pricing like Mistral, the famous AI company,
with multiple dimensions and prepaid credits.
}
href="/templates/per-token/openai"
>
Replicate OpenAI's per-token pricing, the famous AI company behind GPT
models, with multiple dimensions based on models and action types.
## Hybrid pricing
}
href="/templates/hybrid/segment"
>
Build a hybrid pricing and billing system like Segment, the CDP leader,
based on subscription plans, with a usage-based component that makes your
revenue grow with your users.
## Per-transaction pricing
}
href="/templates/per-transaction/stripe"
>
Implement a per-transaction pricing model like Stripe, the leading payments
infrastructure company, including fees based on the total amount and number
of transactions.
## Pay-as-you-go pricing
}
href="/templates/payg/algolia"
>
Discover how Algolia, the search and discovery platform, increases
conversion with commitment-free pricing options that adapt to customers’
needs.
}
href="/templates/payg/bigquery"
>
Implement a pay-as-you-go pricing model and offer free upfront credits to new users like Google BigQuery, the data analytics plaform.
## Per-seat pricing
}
href="/templates/per-seat/notion"
>
Set up a per-user pricing like Notion, the collaboration software for
innovative teams, including plans based on the number of users and prepaid
credits.
# Clone Algolia pricing
Replicate Algolia's pay-as-you-go pricing model with Lago.
In this article, you will learn how to build a ‘pay-as-you-go’ billing system.
This template is suitable for companies whose pricing fully depends on usage, such as cloud service providers and API companies, that only charge their customers for the resources they consume.
## Summary
Create a billable metric to track request usage.
[(More here)](#step-1-aggregate-usage-with-filters).
Set up a package pricing model.
[(More here)](#step-2-set-up-a-per-token-pricing).
Leverage subscriptions for a reduced price.
[(More here)](#step-3-ingest-usage-in-real-time).
## Pricing structure
For its two main products, Algolia Search and Algolia Recommend, the platform offers its customers to subscribe for free and only pay based on usage.
| Model | Search API | Recommend API |
| ----------------------- | ----------------------- | ----------------------- |
| Monthly price | \$1.50 / 1,000 requests | \$0.60 / 1,000 requests |
| Free usage (each month) | 10,000 requests | 10,000 requests |
Although users don’t need to subscribe to access the platform, Algolia offers its customers **discounts** based on volume and commitment (rates available upon request).
We are going to teach you how to replicate this pricing with our billing solution.
## Step 1: Aggregate usage to compute number of requests
Lago monitors consumption by converting events into billable metrics. For Algolia, there would be two billable metrics based on the number of requests for the Search and Recommendation APIs.
As the platform handles **high volumes of requests**, it would be inefficient to create an event each time a request is made. Instead, Algolia could simply send an event once an hour or hour a day with the total number of requests.
Through the user interface, we have created two billable metrics called **‘Search requests’** and **‘Recommend requests’**. For these metrics, we use the ‘sum’ aggregation type based on the volume of requests.
At the end of the billing period, Lago will calculate the sum of requests for each metric using the value of each event (i.e. the event property) and reset the amount to 0 as the aggregation type is metered.
```bash Create billable metrics
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Search Requests",
"code": "search_requests",
"description": "Requests made via the Search API",
"aggregation_type": "sum_agg",
"weighted_interval": null,
"recurring": false,
"field_name": "search_requests_volume",
"filters": []
}
}
```
## Step 2: Create a plan with multiple charges
Now that we have all our billable metrics, we can replicate Algolia’s pricing. As this is a ‘pay-as-you-go’ plan, there is no subscription fee. In the plan settings, we can simply define a monthly billing period and then add our charges.
For both charges, we use the **package pricing model**. This model allows us to create packages of units and define a unique package price. Customers will be charged for usage based on packages of 1,000 requests. Algolia offers 10,000 requests for free each month, for both APIs. Beyond this limit, each ‘opened’ package is due, which means that 800 Search requests cost the same price as 1,000 requests (i.e. \$1.50).
At the end of each billing period (i.e. each month), Lago will automatically invoice each customer according to their consumption, then all counts and calculations will be reset to zero for the next period.
```bash Create a plan with multiple charges
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Algolia Starter",
"code": "algolia_starter",
"interval": "monthly",
"amount_cents": 0,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": false,
"charges": [
{
"billable_metric_id": "15879740-102e-43bd-a6bc-15d865bb1b85",
"billable_metric_code": "search_requests",
"charge_model": "package",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"amount": "1.50",
"free_units": 10000,
"package_size": 1000
},
"filters": [],
"taxes": []
}
],
}
}
```
## Step 3: Offer volume and commitment discounts through subscriptions
*“When committing to the equivalent of 100 Search units per month or more, you automatically unlock a discount compared to PAYGO. Please contact sales for more information.”*
Algolia doesn't provide much information about their volume and commitment discounts but we know that customers who commit to making at least 100,000 Search requests per month (for Algolia, a “Search unit” is a package of 1,000 requests) can benefit from a **reduced price**.
We are going to make some assumptions to see how we could implement this logic.
If we want to keep our package pricing model, we should convert the commitment part of our plan into a **subscription**.
With the standard pricing, 100,000 requests would be charged \$150 (i.e. 100 packages of 1,000 requests at \$1.50 each). Since we want to offer a discount to our customers, we can create a new plan with a monthly subscription of \$120, paid in advance. Then, we set the package price for 1000 requests at \$1.20. Also, we include 100,000 free units, which are covered by the subscription fee.
```bash Introduce a subscription
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Algolia committed",
"code": "algolia_committed",
"interval": "monthly",
"amount_cents": 12000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"charges": [
{
"billable_metric_id": "15879740-102e-43bd-a6bc-15d865bb1b85",
"billable_metric_code": "search_requests",
"charge_model": "package",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"amount": "1.20",
"free_units": 10000,
"package_size": 1000
},
"filters": [],
"taxes": []
}
],
"taxes": []
}
```
Another option would be to drop the package pricing model and use the **graduated pricing model**. This model would allow us to create several tiers with different unit prices.
For the first 100,000 requests included in the subscription, we set a flat fee of \$0 and then apply a decreasing unit price to offer a volume discount.
```bash Implement volume discount
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Algolia committed",
"code": "algolia_committed",
"interval": "monthly",
"amount_cents": 12000,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": true,
"charges": [
{
"billable_metric_id": "15879740-102e-43bd-a6bc-15d865bb1b85",
"billable_metric_code": "search_requests",
"charge_model": "graduated",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"graduated_ranges": [
{
"to_value": 100000,
"from_value": 0,
"flat_amount": "0",
"per_unit_amount": "0"
},
{
"to_value": 150000,
"from_value": 100001,
"flat_amount": "0",
"per_unit_amount": "0.0011"
},
{
"to_value": null,
"from_value": 150001,
"flat_amount": "0",
"per_unit_amount": "0.001"
}
]
},
"filters": [],
"taxes": []
}
],
"taxes": []
}
```
## Wrap-up
‘Pay-as-you-go’ pricing strategies are popular among API companies like Algolia.
With Lago, you can adapt this template to your products and services, using some of our most popular features:
1. **Plan models**, with or without subscription;
2. **Billable metrics**, including the ‘sum’ aggregation type; and
3. **Charges**, including our package and graduated pricing models.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Clone Google BigQuery pricing
Replicate BigQuery's pay-as-you-go pricing model and offer free upfront credits with Lago.
In this article, you will learn how to offer free upfront credits for new users on a ‘pay-as-you-go’ pricing model.
This template is fitted for infra companies, like this BigQuery example, but is also widely used among AI companies to let new users try their products easily.
[Mistral](https://mistral.ai/news/2024-ft-hackathon/#:~:text=We%20offer%20%24100%20free%20credits%20to%20selected%20hackathon%20participants) or [Perplexity](https://docs.perplexity.ai/docs/pricing#:~:text=pplx%2Dapi%20implements%20a%20usage,of%20free%20credit%20every%20month) are other great examples.
## Summary
Aggregate usage to compute number of requests.
[(More here)](#aggregate-usage-to-compute-number-of-requests).
Create a plan with graduated charges.
[(More here)](#create-a-plan-with-graduated-charges).
Set up free credits.
[(More here)](#step-2-create-a-wallet-to-offer-free-credits).
Send usage events to get started.
[(More here)](#step-3-record-customer-usage-to-start-invoicing-customers).
## Pricing structure
BigQuery offers customers the possibility to subscribe for free and only pay based on usage. For new customers, the platform offers \$300 worth of credits during 90 days to try the product completely for free.
| Plan | Cost per volume of data scanned |
| ----------------- | ---------------------------------------------- |
| On-Demand pricing | \$6.25 per TiB (a measure of compute capacity) |
In this article, we are going to show you how to replicate this pricing with Lago’s billing solution.
## Step 1: Configure your pay-as-you-go pricing
### Aggregate usage to compute number of requests
Lago’s **billable metric** allows you to meter and aggregate customer events according to specific rules. For BigQuery, the billable metric will sum the total volume of data scanned.
As the platform handles high volumes of requests, it would be inefficient to create an event each time a query is made.
Instead, BigQuery could simply send an event once an hour or hour a day with the total volume of data processed.
Through the user interface, we created one ‘Data processed’ **billable metric**. For this metric, we use the `sum` aggregation type based on the volume of data processed.
At the end of the billing period, Lago calculates the total volume of processed data for the billable metric using the value contained in each event (i.e. the event property) and reset the amount to 0 as the aggregation type is **metered**.
```bash Create billable metrics
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Data processed",
"code": “data_processed",
"description": "Total volume of data scanned by BigQuery",
"aggregation_type": "sum",
"recurring": false,
"field_name": "data_processed_volume",
"filters": [
]
}
}'
```
### Create a plan with graduated charges
We now have our billable metric to replicate BigQuery’s pricing. As this is a ‘pay-as-you-go’ plan, there is no subscription fee.
In the plan setting, we only need to define a monthly billing period and set a specific pricing to our charges.
We use the **graduated charge** model since BigQuery offers the first unit for free.
At the end of each billing period (i.e. each month), Lago will automatically invoice each customer according to their consumption, then all counts and calculations will be reset to zero for the next period.
```bash Create a plan with graduated charges
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "BigQuery On-Demand",
"code": "bigquery_on_demand",
"interval": "monthly",
"amount_cents": 0,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": false,
"charges": [
{
"billable_metric_id": "__BILLABLE_METRIC_ID__",
"billable_metric_code": "data_processed",
"charge_model": "graduated",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"graduated_ranges": [
{
"from_value": 0,
"to_value": 10000,
"per_unit_amount": "0",
"flat_amount": "0"
},
{
"from_value": 10001,
"to_value": null,
"per_unit_amount": "6.25",
"flat_amount": "0"
}
]
},
"filters": [],
"taxes": []
}
],
}
}
```
## Step 2: Create a wallet to offer free credits
*“Start your 90-day free BigQuery trial which includes \$300 worth of free usage”*
BigQuery lets new users try its product for free by offering upfront credits valid for 90 days.
We can replicate this logic using Lago’s **wallet** feature and add **prepaid free credits** to it.
For each customer, we need to create a wallet and offer \$300 of upfront free credits to replicate BigQuery’s offer. To do so, we set up the value of each credit at \$1.00 and grant 300 credits that customers will receive when creating their account.
The credits are valid for 90 days, so we will also set an expiration date on the wallet. After this date, the wallet will expire and all remaining credits won’t be actionable.
```bash Create a wallet on a customer
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "https://api.getlago.com/api/v1/wallets" \
--header "Authorization: Bearer $__YOUR_API_KEY__" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"name": "Free trial offer",
"rate_amount": "1.00",
"currency": "USD",
"external_customer_id": "__EXTERNAL_CUSTOMER_ID__",
"paid_credits": "0",
"granted_credits": "30000"
}
}'
```
## Step 3: Record customer usage to start invoicing customers
Once you have set up a billable metric, plan and wallet, you can start sending customer usage events to Lago. Events will be aggregated per the billable metric rules and Lago will price it charges according to the charges defined in the plan.
You can send an event once an hour or hour a day with the total volume of data processed. You can batch up to 100 events in a single request.
```bash Send usage events
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "__UNIQUE_ID__",
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"timestamp": $(date +%s),
"properties": {
"data_processed_volume": "10"
},
}
}
}'
```
Lago’s engine will compute the ongoing wallet balance based on the customer usage. At the end of the plan’s billing cycle, if the wallet balance is positive, an invoice will be generated but the offered credits will cover the customer usage. On the contrary, if the wallet balance is negative, the outstanding amount will be invoiced to the customer for payment.
Below is an invoice example where the usage exceeded the offered credits. Credits are automatically deducted from the amount due.
## Wrap-up
Offering free upfront credits is a popular strategy among AI and infra companies with pay-as-you-go models like BigQuery.
With Lago, you can adapt this template to your products and services using:
1. Configure your pay-as-you-go pricing by aggregate using a **billable metric**;
2. Add this billable metric as **graduated charges** to a plan; and
3. Create a **wallet** and add prepaid free credits.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Clone Notion pricing
Replicate Notion's per-seat pricing model with Lago.
Set up a per-user (or 'per-seat) pricing like [Notion](https://www.notion.so/product), the collaboration software for innovative teams, including plans based on the number of users and prepaid credits.
In this article, you will learn how to build a 'fair' billing system, with charges calculated according to the number of days of use.
This template is suitable for companies whose pricing depends on persistent metrics, such as productivity software (e.g. number of days users are active), fintechs (e.g. number of days payment cards are active) and data platforms (e.g. number of days integrations are active).
## Summary
Create a billable metric to track user activity. [(More
here)](#step-1-create-recurring-metrics).
Set up prorata pricing for a pay-as-you-go plan. [(More
here)](#step-2-set-up-a-fair-pricing-model).
Create a wallet to assign credits. [(More
here)](#step-3-offer-credits-to-your-customers).
## Pricing structure
Notion offers a Personal Pro plan for individuals who want to collaborate with friends or clients, and a Team plan through which members can set up a collaborative workspace. While the Personal Pro plan is limited to one member, the Team plan allows companies to invite as many members as they need.
| Model | Personal Pro plan | Team plan |
| ----------------------- | ------------------ | ---------------------------- |
| Pages and blocks | Unlimited | Unlimited |
| Members | Just one | Unlimited |
| Guests | Unlimited | Unlimited |
| File uploads | Unlimited | Unlimited |
| Collaborative workspace | No | Yes |
| Price | \$5 billed monthly | \$10 per user billed monthly |
In its FAQ section, Notion explains how adding and removing members work:
*"If you added members, your account will be charged a prorated amount based on the percentage of the billing cycle left at the time each member was added. If you removed members, your account will be credited in the same way."*
Notion's per-seat pricing is what we call a **'fair' pricing model**, where fees are calculated based on the number of days each user is active.
In addition to this, users can complete tasks to earn credits with which they can pay their Notion bill:
*"You can earn credit by using Notion across your devices and trying out new features. Go to the Earn Credit tab in Settings & Members to learn more."*
Here's how you can replicate this pricing and billing system with Lago.
## Step 1: Create recurring metrics
Lago monitors usage by converting events into billable metrics. Notion's pricing is based on users, so we need to create a billable metric to keep track of the users associated with each customer account.
There are two types of metrics:
* **Metered metrics** that are reset to zero at the end of each billing period; and
* **Recurring metrics** that can be carried over several billing periods.
When a new member is added to a Notion account, they are likely to remain active for some time (probably more than just a month). Therefore, we should create a recurring metric for our users.
The aggregation type is a recurring **count unique** and will allow us to record the period of activity of each user (i.e. from the day the member is added to the account until the day they are removed).
When a new member is successfully added to the customer account, the backend system will generate an event, including the **user\_id** and **"operation\_type": "add"**. When a member is removed from the customer account, the backend system will also generate an event, including the **user\_id** and **"operation\_type": "remove"**.
At the end of the billing period, Lago will automatically calculate the number of days of activity for each user.
```bash
# Create a recurring billable metric
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Users",
"code": "users",
"description": "Team members with access to the collaborative space",
"aggregation_type": "unique_count_agg",
"weighted_interval": null,
"recurring": true,
"field_name": "user_id",
"filters": []
}
}
```
## Step 2: Set up a 'fair' pricing model
When creating a new plan, the first step is to define the plan model, including billing frequency and subscription fee. Notion's Team plan is **'pay-as-you-go'**, which means that there's no subscription fee (i.e. customers only pay for what they use).
This plan can be billed annually (\$96 per user) or monthly (\$10 per user). Depending on the billing cycle, we add a **standard charge** of \$96 or \$10, associated with our billable metric. For example, for the monthly plan, one unit represents one active user for a full month.
We turn **Prorate charge amount** on so that when a new user is added in the middle of the billing cycle, they will be billed a prorated amount that corresponds to the percentage of the billing cycle remaining. This same logic is also applied when users are removed.
To understand how it works, we can add a new customer and assign them the monthly Team plan we just created. Today is October 9th and a member is immediately added to the customer account. In the **debugger**, we can see the corresponding event, sent by the backend system via the API.
In the **'Usage' tab** of the customer view, we can see that the customer's current usage is \$7.42. As there's one active user and 23 days left in October (including October 9th), the billing system plans to bill 0.74194 units at the end of the period (23 days left divided by 31 days in October).
```bash
# Create a plan with prorata
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Notion Team plan",
"code": "notion_team_plan",
"interval": "monthly",
"amount_cents": 0,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": false,
"bill_charges_monthly": null,
"charges": [
{
"billable_metric_id": "d4f8056c-6321-4a82-9cd7-1e08313764f4",
"billable_metric_code": "users",
"charge_model": "standard",
"invoiceable": true,
"pay_in_advance": false,
"prorated": true,
"min_amount_cents": 0,
"properties": {
"amount": "10"
},
"filters": [],
"taxes": []
}
],
}
}
```
If the same user is removed before the end of the month, Lago will automatically recalculate the number of **billable days** (i.e. the number of billing units).
## Step 3: Offer credits to your customers
Now that our pricing is ready, we can set up our credit system. Notion customers earn credits when they use the app across different devices and try out new features.
In the **'Wallets' tab** of the customer view, we can create a new wallet, which will allow us to grant credits to our customer. If later they complete additional tasks, we'll be able to top up their wallet with free credits.
Credits are automatically deducted from the customer's next invoice(s).
```bash
# Create a wallet
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"name": "Notion Credits",
"rate_amount": "1.0",
"paid_credits": "0.0",
"granted_credits": "10.0",
"currency": "USD",
"expiration_at": null,
"expiration_date": null,
"recurring_transaction_rules": []
}
}
```
## Wrap-up
For software companies like Notion, implementing a 'fair' per-user pricing model is a good way to **increase transparency and customer satisfaction**.
With Lago, you can create your own persistent metrics to adapt this template to your products and services.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Clone Mistral pricing
Replicate Mistral's per-token pricing model with Lago.
In this article, you will learn how Mistral is using Lago to build a billing system based on AI tokens.
This template is suitable for Large Language Model (LLM) and Generative AI companies whose pricing can vary based on the application or model used.
## Summary
Use single metric to meter tokens with different filters.
[(More here)](#step-1-aggregate-usage-with-filters).
Create a plan to price packages of tokens used.
[(More here)](#step-2-set-up-a-per-token-pricing).
Prepay usage with credits and set top-up rules in real-time.
[(More here)](#step-3-prepay-usage-with-credits).
Retrieve consumed tokens in real-time.
[(More here)](#step-4-ingest-usage-in-real-time).
## Pricing structure
For Mistral, pricing depends on the language model used. Here are several price points they offer:
Prices are per 1M tokens used. You can think of tokens as pieces of words (learn more [here](https://mistral.ai/technology/#models))."
### Open source models pricing
| Models | Input | Output |
| ------------------ | ------------------ | ------------------ |
| open-mistral-7b | \$0.25 / 1M tokens | \$0.25 / 1M tokens |
| open-mixtral-8x7b | \$0.7 / 1M tokens | \$0.7 / 1M tokens |
| open-mixtral-8x22b | \$2 / 1M tokens | \$6 / 1M tokens |
### Optimized models pricing
| Models | Input | Output |
| -------------- | ----------------- | ----------------- |
| mistral-small | \$1 / 1M tokens | \$3 / 1M tokens |
| mistral-medium | \$2.7 / 1M tokens | \$8.1 / 1M tokens |
| mistral-large | \$4 / 1M tokens | \$12 / 1M tokens |
## Step 1: Aggregate usage with filters
Lago monitors usage by converting events into billable metrics. To illustrate how this works, we are going to take the Optimized models (Mistral small, medium or large models) as an example.
Mistral pricing includes a single metric based on the total number of tokens processed on the platform.
To create the corresponding metric, we use the `sum` aggregation type, which will allow us to record usage and calculate the total number of tokens used. In this case, the aggregation type is **metered**. This means that usage is reset to 0 at the beginning of the next billing cycle.
For this metric, there are two dimensions that will impact the price of the token:
* **Model:** mistral-small, mistral-medium or mistral-large; and
* **Type**: Input data or Output data.
Therefore, we propose integrating these two dimensions into our metric as **filters**:
* **Filter #1:** Distinguishes between various models utilized; and
* **Filter #2:** Separates input and output types.
By implementing these filters, we can assign distinct prices to a single metric, based on events' properties.
```bash Create a metric with filters
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Optimized models",
"code": "optimized_models",
"description": "",
"aggregation_type": "sum_agg",
"weighted_interval": null,
"recurring": false,
"field_name": "total",
"filters": [
{
"key": "model",
"values": ["mistral_small", "mistral_medium", "mistral_large]
},
{
"key": "type",
"values": ["input", "output"]
}
]
}
}'
```
## Step 2: Set up a per token pricing
When creating a new plan, the first step is to define the plan model, including billing frequency and subscription fee. Mistral pricing is ‘pay-as-you-go’, which means that there’s no subscription fee (i.e. customers only pay for what they use).
Our plan includes the ‘per 1M tokens’ charge, for which we choose the `package` pricing model.
As we have defined 2 filters (models and type), we can set a specific price for each Model/Type combination.
We can apply the same method to create plans for other models, like *Embeddings* or *Open source models*. Our plan is ready to be used, now let’s see how Lago handles billing by ingesting usage.
```bash Pricing per million tokens
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Pay as you go",
"invoice_display_name": null,
"code": "payg",
"interval": "monthly",
"description": "",
"amount_cents": 0,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": false,
"charges": [
{
"billable_metric_id": "488459e1-f971-42b9-9a6b-63f0719f9006",
"invoice_display_name": null,
"billable_metric_code": "optimized_models",
"charge_model": "package",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"amount": "0",
"free_units": 0,
"package_size": 1
},
"filters": [
{
"invoice_display_name": null,
"properties": {
"amount": "1",
"free_units": 0,
"package_size": 1000000
},
"values": {
"models": ["mistral-small"],
"type": ["input"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "3",
"free_units": 0,
"package_size": 1000000
},
"values": {
"models": ["mistral-small"],
"type": ["output"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "2.7",
"free_units": 0,
"package_size": 1000000
},
"values": {
"models": ["mistral-medium"],
"type": ["input"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "8.1",
"free_units": 0,
"package_size": 1000000
},
"values": {
"models": ["mistral-medium"],
"type": ["output"]
}
}
],
"taxes": []
}
],
"taxes": []
}
}
'
```
## Step 3: Prepay usage with credits
Mistral, following industry practice, employs prepaid credits to facilitate payment collection in advance. Users prepay for credits corresponding to their anticipated model usage.
Moreover, Lago actively monitors credit utilization in real-time and offers customizable top-up rules based on predefined thresholds or time periods.
From the user interface:
* Create a new wallet for prepaid credits;
* Set a ratio (e.g., 1 credit equals \$1);
* Specify the number of credits for offer or purchase; and
* Configure recurring top-up rules based on real-time usage (threshold or interval top-ups).
```bash Prepay usage with credits
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/wallets" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"wallet": {
"name": "Prepaid",
"rate_amount": "1.5",
"paid_credits": "20.0",
"granted_credits": "10.0",
"currency": "USD",
"expiration_at": "2022-07-07",
"external_customer_id": "hooli_1234"
}
}'
```
## Step 4: Ingest usage in real-time
Mistral records the token usage based on the model used. These activities are converted into events that are pushed to Lago.
Let’s take the Optimized Models as an example:
Lago will group events according to:
* The billable metric code;
* The model; and
* The type.
For each charge, the billing system will then automatically calculate the total token usage and corresponding price.
This breakdown will be displayed in the ‘Usage’ tab of the user interface and on the invoice sent to the customer.
```bash Ingest tokens usage via events
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "{{$randomUUID}}",
"code": "optimized_models",
"external_customer_id": "hooli_123",
"properties": {
"tokens": 2000000,
"models": "mistral-small",
"type": "output"
}
}
}'
```
## Wrap-up
Per-token pricing offers flexibility and visibility, and allows LLM and Generative AI companies like Mistral to attract more customers.
With Lago, you can create your own metric dimensions to adapt this template to your products and services.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Clone OpenAI pricing
Replicate OpenAI's per-token pricing model with Lago.
In this article, you will learn how to build a billing system with Lago based on tokens.
This template is suitable for Large Language Model (LLM) and Generative AI companies whose pricing can vary based on the application or model used.
## Summary
Use single metric to meter tokens with different filters.
[(More here)](#step-1-aggregate-usage-with-filters).
Create a plan to price packages of tokens used.
[(More here)](#step-2-set-up-a-per-token-pricing).
Retrieve consumed tokens in real-time.
[(More here)](#step-3-ingest-usage-in-real-time).
## Pricing structure
For OpenAI, pricing depends on the language model used. Here are several price points they offer:
*"Prices are per 1,000 tokens. You can think of tokens as pieces of words, where 1,000 tokens is about 750 words (learn more [here](https://platform.openai.com/tokenizer))."*
### GPT-3.5 Turbo pricing
| Model | Input | Output |
| ----------- | ----------------------- | ---------------------- |
| 4K context | \$0.0015 / 1,000 tokens | \$0.002 / 1,000 tokens |
| 16K context | \$0.003 / 1,000 tokens | \$0.005 / 1,000 tokens |
### GPT-4 pricing
| Model | Input | Output |
| ----------- | --------------------- | --------------------- |
| 8K context | \$0.03 / 1,000 tokens | \$0.06 / 1,000 tokens |
| 32K context | \$0.06 / 1,000 tokens | \$0.12 / 1,000 tokens |
## Step 1: Aggregate usage with filters
Lago monitors usage by converting events into billable metrics. To illustrate how this works, we are going to take GPT-4 as an example. OpenAI’s GPT-4 pricing includes a single metric based on the total number of tokens processed on the platform.
To create the corresponding metric, we use the `sum` aggregation type, which will allow us to record usage and calculate the total number of tokens used. In this case, the aggregation type is **metered**. This means that usage is reset to 0 at the beginning of the next billing cycle.
For this metric, there are two dimensions that will impact the price of the token:
* **Model:** 8K context or 32K context; and
* **Type**: Input data or Output data.
Therefore, we propose integrating these two dimensions into our metric as **filters**:
* **Filter #1:** Distinguishes between various models utilized; and
* **Filter #2:** Separates input and output types.
By implementing these filters, we can assign distinct prices to a single metric, based on events' properties.
```bash Create a metric with filters
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "Tokens",
"code": "tokens",
"description": "",
"aggregation_type": "sum_agg",
"weighted_interval": null,
"recurring": false,
"field_name": "total",
"filters": [
{
"key": "model",
"values": [
"32k",
"8k"
]
},
{
"key": "type",
"values": [
"input",
"output"
]
}
]
}
}'
```
## Step 2: Set up a per token pricing
When creating a new plan, the first step is to define the plan model, including billing frequency and subscription fee. OpenAI pricing is ‘pay-as-you-go’, which means that there’s no subscription fee (i.e. customers only pay for what they use).
Here is how to set the monthly plan for GPT-4. Our plan includes the ‘per 1,000 tokens’ charge, for which we choose the `package` pricing model.
As we have defined 2 filters (models and type), we can set a specific price for each Model/Type combination.
We can apply the same method to create plans for GPT-3.5 Turbo. Our plan is ready to be used, now let’s see how Lago handles billing by ingesting usage.
```bash Pricing per tokens
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Pay as you go",
"invoice_display_name": null,
"code": "payg",
"interval": "monthly",
"description": "",
"amount_cents": 0,
"amount_currency": "USD",
"trial_period": 0.0,
"pay_in_advance": false,
"charges": [
{
"billable_metric_id": "488459e1-f971-42b9-9a6b-63f0719f9006",
"invoice_display_name": null,
"billable_metric_code": "tokens",
"charge_model": "package",
"invoiceable": true,
"pay_in_advance": false,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"amount": "0",
"free_units": 0,
"package_size": 1
},
"filters": [
{
"invoice_display_name": null,
"properties": {
"amount": "0.03",
"free_units": 0,
"package_size": 1000
},
"values": {
"model": ["8k"],
"type": ["input"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "0.06",
"free_units": 0,
"package_size": 1000
},
"values": {
"model": ["8k"],
"type": ["output"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "0.06",
"free_units": 0,
"package_size": 1000
},
"values": {
"model": ["32k"],
"type": ["input"]
}
},
{
"invoice_display_name": null,
"properties": {
"amount": "0.12",
"free_units": 0,
"package_size": 1000
},
"values": {
"model": ["32k"],
"type": ["output"]
}
}
],
"taxes": []
}
],
"taxes": []
}
}
'
```
## Step 3: Ingest usage in real-time
OpenAI records the token usage, the number of images, and the usage of transcribing speech into text. These activities are converted into events that are pushed to Lago.
Let’s take GPT-4 as an example:
Lago will group events according to:
* The billable metric code;
* The model; and
* The type.
For each charge, the billing system will then automatically calculate the total token usage and corresponding price.
This breakdown will be displayed in the ‘Usage’ tab of the user interface and on the invoice sent to the customer.
```bash Ingest tokens usage via events
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "{{$randomUUID}}",
"code": "tokens",
"external_customer_id": "__YOUR_CUSTOMER_ID__",
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"properties": {
"total": 5000,
"model": "8k",
"type": "input"
}
}
}'
```
## Wrap-up
Per-token pricing offers flexibility and visibility, and allows LLM and Generative AI companies like OpenAI to attract more customers.
With Lago, you can create your own metric dimensions to adapt this template to your products and services.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!
# Clone Stripe pricing
Replicate Stripe's per-transaction pricing model with Lago.
Implement a per-transaction pricing model like Stripe, the leading payments infrastructure company, including fees based on the total amount and number of transactions.
In this article, you will learn how to build a per-transaction billing system with Lago, where a single event can trigger instant charges.
This template is suitable for companies whose pricing depends on transactions, such as fintechs and marketplaces that deduct their fees from their customers' revenue.
## Summary
Ensure transactions are promptly recorded as they occur.
[(More here)](#step-1-create-billable-metrics-for-transaction).
Establish a price per transaction, incorporating upfront charges and specifying fixed fees, as well as minimum and maximum spending thresholds per transaction.
[(More here)](##step-2-price-transaction-with-in-advance-charges).
Ingest each new transaction in real-time.
[(More here)](#step-3-ingest-transactions-in-real-time).
Ingest each new transaction in real-time.
[(More here)](#step-4-estimate-fees-for-future-transactions).
## Pricing structure
Stripe offers 'pay-as-you-go' pricing based on successful card charges processed via its platform.
Stripe's API includes many payment options. Rates and fixed fees per transaction vary depending on the payment method.
| Payment Method | Percentage Charge (based on transaction amount) | Fixed Fee (per transaction) |
| ------------------------------- | ----------------------------------------------- | --------------------------- |
| Card payments (online) | 2.9% | \$0.30 |
| Card payments (in-person) | 2.7% | \$0.05 |
| Wallets (Apple Pay, Alipay) | 2.9% | \$0.30 |
| Pre-authorised debits in Canada | 1.0% | \$0.30 |
| SEPA Direct Debit | 0.8% | \$0.30 |
| SOFORT | 1.4% | \$0.30 |
As Stripe supports more 20 payment methods in the US and most of them share the same charge model, we will focus on online card payments.
Here's how you can replicate this pricing with our billing solution.
## Step 1: Create billable metrics for transaction
Lago monitors consumption by converting events into billable metrics. For Stripe's per-transaction pricing, we can create a billable metric for each payment method.
Using the `sum` aggregation type, we create a billable metric that will allow us to record transactions. In this case, the aggregation type is `metered`. It means the aggregated amount is reset to 0 at the beginning of the next billing cycle.
When a successful card charge is processed via the platform, our backend system will generate an `online_payments` event, including the transaction amount.
```bash Create a metric for each transaction
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/billable_metrics" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"billable_metric": {
"name": "SEPA",
"code": "sepa",
"description": "",
"aggregation_type": "sum_agg",
"weighted_interval": null,
"recurring": false,
"field_name": "amount",
"filters": []
}
}'
```
## Step 2: Price transaction with in advance charges
When creating a new plan, the first thing to do is to define the plan model, including billing frequency and subscription fee. Here we can select the monthly plan interval. As we are implementing a 'pay-as-you-go' pricing model, there is no subscription fee.
We want our customers to pay for their use of the payments platform, so we add charges to our plan. Each charge is associated with a billable metric (i.e. one charge per payment method in this case) and has its own pricing structure. In order to replicate Stripe’s pricing, we select the percentage metered charge model then choose pay charge in-advance (`pay_in_advance` is `true`).
Additionally, the option to generate invoice for each event should be turned off as Stripe doesn't bill customers for individual transactions (`invoiceable` is `false`).
The percentage charge model allows us to combine a percentage charge **based on the amount of the transaction and a fixed fee**.
If you want to charge your user on this usage on a monthly basis, you can set up the same way using the Percentage charge model and charge it in arrears.
If we wanted to go even further, we could define free units. For instance, we could:
* Offer the first three transactions; or
* Offer the first \$1,000; or
* Create a model where the first three transactions or first \$1,000 would be free; or
* Specify minimum and maximum transaction spending limits. For instance, ensure a minimum fee of \$2 per transaction, even if the result falls below this threshold.
```bash Pricing percentage fees in-advance
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/plans" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"plan": {
"name": "Basic",
"code": "basic",
"interval": "monthly",
"amount_cents": 0,
"amount_currency": "USD",
"pay_in_advance": false,
"charges": [
{
"billable_metric_id": "32c2e174-2c7c-41e7-983b-3018d08e02c1",
"billable_metric_code": "sepa",
"charge_model": "percentage",
"invoiceable": false,
"pay_in_advance": true,
"prorated": false,
"min_amount_cents": 0,
"properties": {
"rate": "0.8",
"fixed_amount": "0.30"
},
"filters": [],
"taxes": []
}
],
"taxes": []
}
}'
```
## Step 3: Ingest transactions in real-time
Stripe records each transaction based on their type, and charge it instantly. These activities are converted into events that are pushed to Lago.
For each transaction, the billing system will then automatically calculate the total amount to charge to the end user.
This breakdown will be displayed in the 'Usage' tab of the user interface and on the invoice sent to the customer.
```bash Ingest event for each transaction
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"transaction_id": "{{$randomUUID}}",
"code": "sepa",
"external_customer_id": "hooli_1234",
"properties": {
"amount": 200
}
}
}'
```
## Step 4: Estimate fees for future transactions
Stripe records each transaction based on their type, and charge it instantly. These activities are converted into events that are pushed to Lago.
For each transaction, the billing system will then automatically calculate the total amount to charge to the end user.
This breakdown will be displayed in the 'Usage' tab of the user interface and on the invoice sent to the customer.
```bash Estimate a fee for a future transaction
LAGO_URL="https://api.getlago.com"
API_KEY="__YOUR_API_KEY__"
curl --location --request POST "$LAGO_URL/api/v1/events/estimate_fees" \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data-raw '{
"event": {
"external_subscription_id": "__YOUR_SUBSCRIPTION_ID__",
"code": "__BILLABLE_METRIC_CODE__",
"properties": {
"amount": 1200,
}
}
}'
```
## Wrap-up
For fintech companies like Stripe, implementing a per-transaction pricing model is a good way to **increase revenue as customers grow and capture value everytime a transaction is processed**.
With Lago, you can create your own billable metrics and use the percentage charge model paid instantly to adapt this template to your products and services.
Give it a try, click [here](https://www.getlago.com/get-started) to get started!