> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runledger.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runledger.co/_mcp/server.

# Retrieve a customer's usage summary

GET https://api.runledger.co/v1/customers/{customer_id}/usage_summary

What a usage meter shows: for each allowance window, how much was granted, used and held, the share used and when it resets, then the balance pools, the next credits to expire, and the money value of this period's spend. It is read from the ledger, so it works for every customer, with or without allowances: a customer on a plan with no allowances has one window for the plan period and one pool. Use it to draw a meter. Don't use it to decide whether work may start, because lists and summaries can lag by a few seconds and `check()` is the authority. `percent_used` is a decimal from 0 to 1.

Reference: https://docs.runledger.co/api-reference/customers/usage-summary/retrieve

## Authentication

- `Authorization` header (bearer token, required) — A secret key (`rl_sk_test_...`, `rl_sk_live_...`) or a restricted key with limited scopes (`rl_rk_test_...`, `rl_rk_live_...`). A restricted key can carry `agent: true` and an `expires_at`, and is what a coding agent should hold. Keys end in a checksum so secret scanners can recognize them. People create, roll and revoke keys in the dashboard; `GET /v1/api_keys` lists them, masked.

## Request

### Path parameters

- `customer_id` (string, required) — The customer ID (`cus_...`).

### Query parameters

- `subscription` (string, optional) — The subscription (`sub_...`). Defaults to the customer's active one.
- `credit_type` (string, optional) — The credit type (ID or key). Defaults to the plan's.
- `member_id` (string, optional) — Read the windows a `per_member` allowance keeps for this member. Without it, those windows are left out.
- `as_of` (datetime, optional) — Read the summary as it stood at this time. Defaults to now.

## Response

### 200

The summary.

- `object` ("usage_summary", required)
- `customer` (string, required)
- `as_of` (datetime, required)
- `windows` (list of UsageWindow, required)
- `pools` (list of UsagePool, required)
- `livemode` (boolean, required)
- `subscription` (string, optional)
- `credit_type` (string, optional)
- `member_id` (string, optional)
- `spend` (UsageSpend, optional) — The money value of this period's consumption.
- `spend_limits` (list of SpendLimit, optional) — The spend limits that apply, each with what has been spent against it.
- `binding_window` (string, optional) — The key of the window with the least room left, so a meter can show the one that will stop the customer first.

## Errors

### 400 Bad Request Error

The request was malformed or a parameter was invalid. A configuration that fails validation, such as two equally specific overrides with overlapping dates, returns `config_invalid`.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 401 Unauthorized Error

The API key is missing, invalid or revoked.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 403 Forbidden Error

The key can't do this. A restricted or agent key lacks the scope (`insufficient_scope`, with `required_scope`), a live key called a sandbox-only endpoint, an agent tried a live config write that needs a proposal (`proposal_required`), or something only a signed-in person can do.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 404 Not Found Error

No object with that ID exists in this environment.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 429 Too Many Requests Error

Too many requests. Wait for the number of seconds in `Retry-After`.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

### 500 Internal Server Error

Something went wrong on Runledger's side. Safe to retry with the same idempotency key.

- `type` (string, required) — A URI for the error type. It links to the error codes table in the docs, where each `code` is listed with its cause. Branch on `code`, not on `type`.
- `title` (string, required) — A short summary of the error type.
- `status` (integer, required) — The HTTP status code.
- `code` (enum, required) — A stable, machine-readable error code. New codes may be added.
  - Allowed values: `invalid_request`, `parameter_missing`, `parameter_invalid`, `parameter_unknown`, `authentication_failed`, `permission_denied`, `insufficient_scope`, `proposal_required`, `config_invalid`, `livemode_mismatch`, `resource_not_found`, `resource_already_exists`, `idempotency_key_in_use`, `idempotency_key_reused`, `invalid_state`, `outcome_charge_locked`, `hold_not_active`, `insufficient_balance`, `credit_limit_exceeded`, `plan_locked`, `test_clock_advancing`, `provider_error`, `rate_limited`, `api_error`, `service_unavailable`
- `request_id` (string, required) — The ID of the request. Quote it to support, or look it up in request logs.
- `retryable` (boolean, required) — Whether sending the same request again, with the same idempotency key, may succeed.
- `detail` (string, optional) — An explanation of this occurrence. For people; don't parse it.
- `param` (string, optional) — The request parameter at fault, as a dotted path.
- `required_scope` (string, optional) — The scope the call needed, on `insufficient_scope`. Ask a person to widen the key, or reconnect with it.
- `errors` (list of ConfigIssue, optional) — Only with `config_invalid`: each problem the configuration document has, with the path of the part at fault, so an agent can fix the document without a second call.
- `blocked_by` (list of ErrorResponseBlockedByItems, optional) — On an `invalid_state` that names the objects in the way, the objects that must change first. Removing a payment provider lists every routing rule that uses it (`object: routing_rule`) and every customer whose own `payment_provider` names it (`object: customer`), in one list.
- `doc_url` (string, optional) — A link to the error codes table in the docs, where this `code` is listed with its cause.

## Types

### UsageWindow

One meter. Every window that applies to the customer is listed, and `binding_window` on the summary names the one with the least room left.

- `key` (string, required) — The allowance key, or the event name for an `included` window.
- `kind` (enum, required) — `refill` and `cap` come from allowances. `included` is the included quantity of a postpaid rate.
  - Allowed values: `refill`, `cap`, `included`
- `window` (UsageWindowWindow, required)
- `period_start` (datetime, required)
- `resets_at` (datetime, required)
- `granted` (string, required) — Credits granted in the window, the cap for a `cap`, or the included quantity.
- `used` (string, required)
- `held` (string, required) — Active holds against the window. Counted in `remaining`, not in `percent_used`.
- `remaining` (string, required)
- `percent_used` (string, required) — `used` over `granted`, a decimal from 0 to 1. `"0.62"` is 62%.
- `pool` (string, optional)
- `scope` (enum, optional)
  - Allowed values: `customer`, `per_member`

### UsagePool

- `pool` (string, required)
- `posted` (string, required)
- `held` (string, required)
- `available` (string, required)
- `next_expiry` (UsagePoolNextExpiry, optional) — The next credits in the pool to expire.

### UsageSpend

The money value of this period's consumption.

- `this_period` (Money, required) — An amount of money in the currency's minor unit.
- `basis` (enum, required) — `cost_basis`: prepaid credits drawn, valued at the cost basis of the grants they came from. Included and promotional credits are worth zero. `charges`: a postpaid plan's confirmed and pending charges that haven't been invoiced.
  - Allowed values: `cost_basis`, `charges`
- `period_start` (datetime, required)
- `resets_at` (datetime, required)

### SpendLimit

- `id` (string, required)
- `object` ("spend_limit", required)
- `applies_to` (SpendLimitScope, required) — Every condition you send must match, and a limit with none applies to the whole account. Limits are grouped by which of `agent_id`, `member_id`, `team_id` and `pool` they name. Inside a group the most specific one applies to a customer: its own `customer`, then its `plan`, then the account. Every group that applies must have room, so the strictest group decides.
- `period` (SpendLimitPeriod, required)
- `amount` (Money, required) — An amount of money in the currency's minor unit.
- `counts` (enum, required, default: paid_usage) — What counts toward the limit. `paid_usage`: the money value of consumption drawn from paid credits and overage, so included and promotional usage keeps working. `all_usage`: the money value of everything. Buying credits never counts.
  - Allowed values: `paid_usage`, `all_usage`
- `action` (enum, required, default: warn) — `warn` adds warnings and a webhook. `block` also denies in `check()`.
  - Allowed values: `warn`, `block`
- `set_by` (enum, required, default: operator) — `operator`: you set it as policy. `customer`: your customer chose it, through your product or the customer view.
  - Allowed values: `operator`, `customer`
- `enabled` (boolean, required)
- `livemode` (boolean, required)
- `created_at` (datetime, required)
- `key` (string, optional)
- `ceiling` (Money, optional) — An amount of money in the currency's minor unit.
- `alert_at` (list of string, optional)
- `current` (SpendLimitCurrent, optional) — What has been spent against the limit this period. Read-only.
- `actor` (Actor, optional) — Who last changed the limit.

### ConfigIssue

A problem or warning about a part of a configuration document.

- `code` (string, required) — A stable code. New codes may be added.
- `message` (string, required)
- `path` (string, optional) — Where in the document, as a dotted path.

### ErrorResponseBlockedByItems

- `object` (enum, required) — The kind of object in the way: a routing rule, or a customer with a `payment_provider` override.
  - Allowed values: `routing_rule`, `customer`
- `id` (string, required) — The object's ID, `rr_...` for a routing rule and `cus_...` for a customer.

### UsageWindowWindow

- `type` (enum, required) — `period` is the plan's own billing period, used when the plan has no allowances.
  - Allowed values: `fixed`, `session`, `sliding`, `period`
- `duration` (string, required)

### UsagePoolNextExpiry

The next credits in the pool to expire.

- `amount` (string, required)
- `at` (datetime, required)

### Money

An amount of money in the currency's minor unit.

- `amount` (integer, required) — Minor units. 1500 is US$15.00; 1500 is ¥1,500.
- `currency` (string, required) — Lowercase ISO 4217 code.

### SpendLimitScope

Every condition you send must match, and a limit with none applies to the whole account. Limits are grouped by which of `agent_id`, `member_id`, `team_id` and `pool` they name. Inside a group the most specific one applies to a customer: its own `customer`, then its `plan`, then the account. Every group that applies must have room, so the strictest group decides.

- `customer` (string, optional) — A customer (`cus_...`).
- `plan` (string, optional) — A plan (ID or key).
- `agent_id` (string, optional)
- `member_id` (string, optional)
- `team_id` (string, optional)
- `pool` (string, optional) — A pool key.

### SpendLimitPeriod

- `duration` (enum, optional, default: P1M)
  - Allowed values: `P1D`, `P1W`, `P1M`
- `anchor` (enum, optional, default: calendar) — `calendar`: UTC midnight, Monday for a week, the first for a month. `billing_period`: the customer's subscription period. `customer`: a stable reset instant per customer.
  - Allowed values: `calendar`, `billing_period`, `customer`

### SpendLimitCurrent

What has been spent against the limit this period. Read-only.

- `spent` (Money, required) — An amount of money in the currency's minor unit.
- `held` (Money, required) — Active holds, which count toward the limit until they are released or captured.
- `period_start` (datetime, required)
- `resets_at` (datetime, required)

### Actor

Who made a change. Runledger fills it in from the credential, so a client can't claim to be someone else: an API key always acts as itself, the dashboard calls the API as the signed-in person, and the MCP server passes the client's name and the person it acts for. A request that sends a `Runledger-Actor` header is refused with `400 parameter_unknown`.

- `type` (enum, required) — `user`: a signed-in person, including a person at Runledger support acting in your account, whose `name` reads `Runledger support`. `agent`: an agent connected through an OAuth session or an agent key. `key`: any other API key. `rule`: a reversal rule. `system`: Runledger itself, such as a clock.
  - Allowed values: `user`, `agent`, `key`, `rule`, `system`
- `id` (string, optional) — The user, key or agent session ID. Left out for `rule` and `system`, except a change a customer makes on the customer view, which carries the customer session's ID.
- `name` (string, optional) — A display name, such as a person's name, a key's name or the MCP client.
- `on_behalf_of` (string, optional) — The person an agent acts for, when known.
- `client` (string, optional) — The software that made the call, such as an MCP client or SDK.

## Examples

**Response**

```json
{
  "object": "string",
  "customer": "cus_9sF2kq81LmQz",
  "as_of": "2024-01-15T09:30:00Z",
  "windows": [
    {
      "key": "weekly",
      "kind": "refill",
      "window": {
        "type": "fixed",
        "duration": "P1W"
      },
      "period_start": "2024-01-15T09:30:00Z",
      "resets_at": "2024-01-15T09:30:00Z",
      "granted": "1500",
      "used": "930",
      "held": "40",
      "remaining": "530",
      "percent_used": "0.62",
      "pool": "included",
      "scope": "customer"
    }
  ],
  "pools": [
    {
      "pool": "purchased",
      "posted": "4300",
      "held": "0",
      "available": "4300",
      "next_expiry": {
        "amount": "1000",
        "at": "2024-01-15T09:30:00Z"
      }
    }
  ],
  "livemode": true,
  "subscription": "sub_5gT8hY1uIo",
  "credit_type": "ai_credits",
  "member_id": "string",
  "spend": {
    "this_period": {
      "amount": 1500,
      "currency": "usd"
    },
    "basis": "cost_basis",
    "period_start": "2024-01-15T09:30:00Z",
    "resets_at": "2024-01-15T09:30:00Z"
  },
  "spend_limits": [
    {
      "id": "sl_4kP7wD2nRt",
      "object": "string",
      "applies_to": {
        "customer": "string",
        "plan": "string",
        "agent_id": "string",
        "member_id": "string",
        "team_id": "string",
        "pool": "string"
      },
      "period": {
        "duration": "P1M",
        "anchor": "calendar"
      },
      "amount": {
        "amount": 1500,
        "currency": "usd"
      },
      "counts": "paid_usage",
      "action": "warn",
      "set_by": "operator",
      "enabled": true,
      "livemode": true,
      "created_at": "2024-01-15T09:30:00Z",
      "key": "team_monthly_cap",
      "ceiling": {
        "amount": 1500,
        "currency": "usd"
      },
      "alert_at": [
        "string"
      ],
      "current": {
        "spent": {
          "amount": 1500,
          "currency": "usd"
        },
        "held": {
          "amount": 1500,
          "currency": "usd"
        },
        "period_start": "2024-01-15T09:30:00Z",
        "resets_at": "2024-01-15T09:30:00Z"
      },
      "actor": {
        "type": "user",
        "id": "usr_4tN8vB2cXk",
        "name": "Claude Code",
        "on_behalf_of": "usr_4tN8vB2cXk",
        "client": "claude-code"
      }
    }
  ],
  "binding_window": "session"
}
```

**SDK Code**

```python
import requests

url = "https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary"

headers = {"Authorization": "Bearer <api_key>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary';
const options = {method: 'GET', headers: {Authorization: 'Bearer <api_key>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <api_key>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <api_key>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary")
  .header("Authorization", "Bearer <api_key>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary', [
  'headers' => [
    'Authorization' => 'Bearer <api_key>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <api_key>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <api_key>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.runledger.co/v1/customers/cus_9sF2kq81LmQz/usage_summary")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```