cURL
curl --request POST 'https://api.integrateledger.com/v1/features' \
-H "Authorization: Bearer $LEDGER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"id":"api_call","name":"API call","creditCost":1}'import os
from ledger_sdk import Ledger
ledger = Ledger(api_key=os.environ["LEDGER_API_KEY"])
ledger.create_feature(id="api_call", name="API call", credit_cost=1)import { Ledger } from "@ledger/sdk";
const ledger = new Ledger({ apiKey: process.env.LEDGER_API_KEY ?? "" });
await ledger.createFeature({ id: "api_call", name: "API call", creditCost: 1 });const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({id: '<string>', name: '<string>', creditCost: 123})
};
fetch('https://api.integrateledger.com/v1/features', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.integrateledger.com/v1/features",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => '<string>',
'name' => '<string>',
'creditCost' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.integrateledger.com/v1/features"
payload := strings.NewReader("{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.integrateledger.com/v1/features")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.integrateledger.com/v1/features")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}"
response = http.request(request)
puts response.read_body{
"item": {
"id": "api_call",
"name": "API call",
"creditCost": 1
},
"changed": true
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Features
Create a feature
Create one metered feature without replacing other catalog items.
POST
/
v1
/
features
cURL
curl --request POST 'https://api.integrateledger.com/v1/features' \
-H "Authorization: Bearer $LEDGER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"id":"api_call","name":"API call","creditCost":1}'import os
from ledger_sdk import Ledger
ledger = Ledger(api_key=os.environ["LEDGER_API_KEY"])
ledger.create_feature(id="api_call", name="API call", credit_cost=1)import { Ledger } from "@ledger/sdk";
const ledger = new Ledger({ apiKey: process.env.LEDGER_API_KEY ?? "" });
await ledger.createFeature({ id: "api_call", name: "API call", creditCost: 1 });const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({id: '<string>', name: '<string>', creditCost: 123})
};
fetch('https://api.integrateledger.com/v1/features', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.integrateledger.com/v1/features",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => '<string>',
'name' => '<string>',
'creditCost' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.integrateledger.com/v1/features"
payload := strings.NewReader("{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.integrateledger.com/v1/features")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.integrateledger.com/v1/features")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"creditCost\": 123\n}"
response = http.request(request)
puts response.read_body{
"item": {
"id": "api_call",
"name": "API call",
"creditCost": 1
},
"changed": true
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Create one metered feature without replacing other catalog items. A feature names an action in your application and sets how many credits one successful use costs. For example, a feature with ID
api_call and creditCost: 1 charges one credit per tracked API call.
Define the meter
creditCost must be a positive integer. The feature ID is your stable identifier for Check credits and Record usage. It accepts letters, numbers, underscores, and hyphens, up to 100 characters. name is a display label of at most 120 characters.
The API returns the created item with changed: true. Creating another active feature with the same ID returns 409 already_exists. Feature creation is independent of plans and credit packs and does not call Stripe.
Use it from your backend
Callcheck before your application performs the action, then call track after the action succeeds. A check does not reserve credits; track makes its own balance decision. Give every logical action a unique request_id, and reuse that ID only for a retry of the same action. A repeated track returns idempotent: true without another charge.
Update a feature changes the cost of future tracked events. Previously recorded usage keeps its original charge. Archive a feature removes it from active lists and future checks while retaining usage history. See Credits and usage for concurrency and error handling.Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json