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