PersonalBusinessEnterprise
    In a rush? Schedule an Appointment
    Fetching local time...
    Anytime CapitalforBusiness
    Pricing

    Get started

    • Overview
    • Quickstart
    • Test mode
    • Guides & recipes
    • Switch from Stripe
    • Import from Shopify
    • Import from WooCommerce
    • Import from Square
    • Import a CSV file
    • Stripe API mapping
    • Pricing
    • Support
    • FAQ

    Payments

    • Checkout & website
    • Guide: Next.js checkout
    • In person (QR)
    • Payment methods
    • Stablecoin checkout
    • Guide: take stablecoins
    • Fraud rules & 3D Secure
    • Dispute evidence
    • International customers
    • Guide: safe refunds
    • Bank transfers on invoices

    Billing

    • Subscription discounts
    • Guide: sell subscriptions
    • Usage billing
    • Guide: report usage

    Money movement

    • Payout options
    • Guide: reconcile payouts
    • Accounting sync
    • Revenue analytics

    Developers

    • Authentication
    • Errors & retries
    • Pagination
    • Idempotency
    • Rate limits
    • Webhooks
    • Verify webhooks
    • Node SDK (preview)
    • CLI (preview)
    • Postman collection

    AI

    • AI agents hub
    • Safe AI agents
    • Custom agents
    • Prompt library

    Integrations

    • Website builders
    • Shopify
    • Shopify orders by invoice
    • WooCommerce
    • Zapier
    • Slack, Discord and Teams

    Reference

    • Payments
    • Refunds
    • Disputes
    • Payment links
    • Invoices
    • Customers
    • Products
    • Subscriptions & plans
    • Discount codes
    • Meters & usage events
    • Payouts & balance
    • Webhook endpoints
    • Events
    • Test helpers
    • OpenAPI spec
    • Error codes
    • Changelog
    • Glossary

    For AI tools

    • llms-full.txt
    • MCP server
    • openapi.json
    Docs menu · Meters & usage events

    Get started

    • Overview
    • Quickstart
    • Test mode
    • Guides & recipes
    • Switch from Stripe
    • Import from Shopify
    • Import from WooCommerce
    • Import from Square
    • Import a CSV file
    • Stripe API mapping
    • Pricing
    • Support
    • FAQ

    Payments

    • Checkout & website
    • Guide: Next.js checkout
    • In person (QR)
    • Payment methods
    • Stablecoin checkout
    • Guide: take stablecoins
    • Fraud rules & 3D Secure
    • Dispute evidence
    • International customers
    • Guide: safe refunds
    • Bank transfers on invoices

    Billing

    • Subscription discounts
    • Guide: sell subscriptions
    • Usage billing
    • Guide: report usage

    Money movement

    • Payout options
    • Guide: reconcile payouts
    • Accounting sync
    • Revenue analytics

    Developers

    • Authentication
    • Errors & retries
    • Pagination
    • Idempotency
    • Rate limits
    • Webhooks
    • Verify webhooks
    • Node SDK (preview)
    • CLI (preview)
    • Postman collection

    AI

    • AI agents hub
    • Safe AI agents
    • Custom agents
    • Prompt library

    Integrations

    • Website builders
    • Shopify
    • Shopify orders by invoice
    • WooCommerce
    • Zapier
    • Slack, Discord and Teams

    Reference

    • Payments
    • Refunds
    • Disputes
    • Payment links
    • Invoices
    • Customers
    • Products
    • Subscriptions & plans
    • Discount codes
    • Meters & usage events
    • Payouts & balance
    • Webhook endpoints
    • Events
    • Test helpers
    • OpenAPI spec
    • Error codes
    • Changelog
    • Glossary

    For AI tools

    • llms-full.txt
    • MCP server
    • openapi.json
    DocsReferenceMeters & usage events

    Meters and usage events API

    Send usage events to Anytime Capital meters one at a time or in batches of 100, list your meters and read a customer's usage, for usage-based billing.

    View as MarkdownOpen in Claude

    Meters count what customers use (API calls, seats, gigabytes) and bill it each period. Make meters on the Meters tab of Subscriptions in the dashboard; this API sends usage to them and reads it back. How usage turns into invoices is on Usage billing; a complete sender is in the usage recipe. Reading needs subscriptions:read, sending subscriptions:write.

    TopicDetail
    Endpoints`POST /api/v1/meter-events`, `POST /api/v1/meter-events/batch`, `GET /api/v1/meters`, `GET /api/v1/meters/{id}/usage`
    Key permissionssubscriptions:write, subscriptions:read
    Samplescurl; Node.js 18+ with the built-in fetch (in an ES module); the Node SDK (preview: not on npm yet); Python with requests.
    Every request can also answer401 UNAUTHORIZED, 401 API_KEY_EXPIRED, 403 NOT_ENROLLED, 403 PERMISSION_DENIED, 403 IP_NOT_ALLOWED, 429 RATE_LIMITED, 500 INTERNAL_ERROR. See Error codes.

    Idempotency is per event

    Usage events don't use the Idempotency-Key header. Each event carries its own idempotencyKey in the body (your request id, say), remembered for good: sending the same event again answers 200 with the event already recorded, so retries never count twice.

    The meter object

    JSON
    {
      "object": "meter",
      "livemode": true,
      "id": "mtr_8fKq2LmNpR4sT6vW9xYz",
      "name": "API calls",
      "eventName": "api_call",
      "aggregation": "count",
      "unitLabel": "API call",
      "unitPriceCents": "0.25",
      "includedUnits": "1000",
      "status": "active",
      "createdAt": "2026-10-01T15:04:05.000Z"
    }
    FieldTypeDescription
    objectstringThe type of object. Always meter.
    livemodebooleanFalse for test-mode data (an ak_test_ key); true for live data.
    idstringmtr_ followed by 20 letters and digits.
    namestringShown on invoices.
    eventNamestringWhat your events name to reach this meter. Unique per business.
    aggregationstringHow a period's events add up: sum adds values, count counts events, max takes the highest value, last the latest.
    unitLabelstringThe unit, e.g. "API call".
    unitPriceCentsstringPrice per unit in cents, as a decimal string (fractions of a cent allowed).
    includedUnitsstringUnits each period before billing starts, as a decimal string.
    statusstringactive, or archived (it stops taking events and billing).
    createdAtstring (date-time)Created.

    The meter event object

    JSON
    {
      "object": "meter_event",
      "livemode": true,
      "id": "mev_48213",
      "meter": "mtr_8fKq2LmNpR4sT6vW9xYz",
      "eventName": "api_call",
      "customer": "cus_1042",
      "customerEmail": "jordan@example.com",
      "value": "1",
      "timestamp": "2026-10-24T09:30:00.000Z",
      "idempotencyKey": "req_7f3a9c",
      "created": "2026-10-24T09:30:01.214Z"
    }
    FieldTypeDescription
    objectstringThe type of object. Always meter_event.
    livemodebooleanFalse for test-mode data (an ak_test_ key); true for live data.
    idstringmev_…
    meterstringmtr_…
    eventNamestringThe meter's event name.
    customerstring or nullcus_… when the customer is saved.
    customerEmailstringLower-cased.
    valuestringThe usage, as a decimal string.
    timestampstring (date-time)When the usage happened.
    idempotencyKeystringYour key for this event.
    createdstring (date-time)Recorded.

    The usage object

    JSON
    {
      "object": "meter_usage",
      "livemode": true,
      "meter": "mtr_8fKq2LmNpR4sT6vW9xYz",
      "customer": "cus_1042",
      "customerEmail": "jordan@example.com",
      "from": "2026-10-01T00:00:00.000Z",
      "to": "2026-10-03T00:00:00.000Z",
      "aggregation": "count",
      "quantity": "1210",
      "eventCount": 1210,
      "daily": [
        {
          "date": "2026-10-01",
          "quantity": "480"
        },
        {
          "date": "2026-10-02",
          "quantity": "730"
        }
      ]
    }
    FieldTypeDescription
    objectstringThe type of object. Always meter_usage.
    livemodebooleanFalse for test-mode data (an ak_test_ key); true for live data.
    meterstringmtr_…
    customerstring or nullcus_… when the customer is saved.
    customerEmailstringLower-cased.
    fromstring (date-time)Window start.
    tostring (date-time)Window end.
    aggregationstringOne of sum, count, max, last.
    quantitystringUsage over the window, as a decimal string.
    eventCountintegerEvents in the window.
    dailyobject[]
    daily[].datestringThe UTC day, YYYY-MM-DD.
    daily[].quantitystringUsage that day, as a decimal string.

    Endpoints

    Record usage

    POST/api/v1/meter-events
    Permission subscriptions:writeIdempotent by each event's idempotencyKey.

    Record one usage event against a meter, by the meter's event name. Each event carries its own idempotencyKey in the body (the Idempotency-Key header isn't used here): repeating it with the same event answers 200 with Idempotent-Replayed: true; with a different event, 409 IDEMPOTENCY_KEY_REUSED. 422 for a timestamp more than 5 minutes ahead, older than 400 days, or in a period already billed.

    Body

    eventName
    stringrequired
    The meter's event name.
    customerId
    string
    cus_…. Send this or customerEmail.
    customerEmail
    string
    The customer's email. Send this or customerId.
    value
    number or string
    The usage, at least 0 with up to 6 decimals. Defaults to 1.
    timestamp
    string (date-time)
    ISO 8601 with an offset. Defaults to now; at most 5 minutes ahead.
    idempotencyKey
    stringrequired
    Required. Your unique key for this event, 1–255 printable characters, such as your own request id. Sending it again with the same event answers 200 with the event already recorded; nothing is counted twice.
    Request
    curl -X POST https://anytime-capital.com/api/v1/meter-events \
      -H "Authorization: Bearer $ANYTIME_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "eventName": "api_call",
        "customerId": "cus_1042",
        "value": 1,
        "idempotencyKey": "req_7f3a9c"
      }'
    const res = await fetch("https://anytime-capital.com/api/v1/meter-events", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        eventName: "api_call",
        customerId: "cus_1042",
        value: 1,
        idempotencyKey: "req_7f3a9c",
      }),
    });
    const event = await res.json();
    if (!res.ok) throw new Error(`${event.error.code}: ${event.error.message}`);
    import os
    
    import requests
    
    res = requests.post(
        "https://anytime-capital.com/api/v1/meter-events",
        headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
        json={
            "eventName": "api_call",
            "customerId": "cus_1042",
            "value": 1,
            "idempotencyKey": "req_7f3a9c",
        },
        timeout=30,
    )
    event = res.json()
    if not res.ok:
        raise RuntimeError(f"{event['error']['code']}: {event['error']['message']}")
    Response 201
    {
      "object": "meter_event",
      "livemode": true,
      "id": "mev_48213",
      "meter": "mtr_8fKq2LmNpR4sT6vW9xYz",
      "eventName": "api_call",
      "customer": "cus_1042",
      "customerEmail": "jordan@example.com",
      "value": "1",
      "timestamp": "2026-10-24T09:30:00.000Z",
      "idempotencyKey": "req_7f3a9c",
      "created": "2026-10-24T09:30:01.214Z"
    }

    Errors

    400INVALID_JSON
    The body isn't valid JSON, or couldn't be read. An empty body reads as {}. Send Content-Type: application/json and a JSON object.
    400INVALID_INPUT
    A field, filter, limit or cursor is missing or invalid. The message starts with the field's name, as in amountCents: …, or reads Invalid cursor. Fix the named field. Don't retry the same request unchanged.
    400CUSTOMER_MISMATCH
    customerId and customerEmail name different customers. Send one of them.
    404METER_NOT_FOUND
    No active meter has this eventName. Check the meter's event name on the Meters tab of Subscriptions, or with GET /api/v1/meters.
    404CUSTOMER_NOT_FOUND
    No saved customer has this customerId. Send the customer's cus_… id, or customerEmail instead.
    409IDEMPOTENCY_KEY_REUSED
    The usage event's idempotencyKey was already used for a different event. Send a new idempotencyKey for each event; repeat a key only to resend the same event.
    422CUSTOMER_HAS_NO_EMAIL
    The customer has no email address, and usage is matched to subscriptions by email. Add an email to the customer in the dashboard, or send customerEmail.
    422TIMESTAMP_IN_FUTURE
    The event's timestamp is more than five minutes ahead of our clock. Send the time the usage happened, or leave timestamp out for now.
    422TIMESTAMP_TOO_OLD
    The event's timestamp is more than 400 days ago. Usage that old can't be billed; drop the event.
    422PERIOD_CLOSED
    The timestamp falls in a period already billed for this customer and meter. Send usage from the end of the billed period on. The message says when that is.

    Record usage in a batch

    POST/api/v1/meter-events/batch
    Permission subscriptions:writeIdempotent by each event's idempotencyKey.

    Up to 100 usage events at once, each with its own idempotencyKey. Each is answered by its index: created, duplicate or refused with its own error. The HTTP status is 200 whenever the batch itself is valid: read each event's status. A refused event carries the code a single event would get (METER_NOT_FOUND, PERIOD_CLOSED, IDEMPOTENCY_KEY_REUSED…).

    Body

    events
    object[]required
    1–100 items.
    events[].eventName
    stringrequired
    The meter's event name.
    events[].customerId
    string
    cus_…. Send this or customerEmail.
    events[].customerEmail
    string
    The customer's email. Send this or customerId.
    events[].value
    number or string
    The usage, at least 0 with up to 6 decimals. Defaults to 1.
    events[].timestamp
    string (date-time)
    ISO 8601 with an offset. Defaults to now; at most 5 minutes ahead.
    events[].idempotencyKey
    stringrequired
    Your unique key for this event, 1–255 printable characters.
    Request
    curl -X POST https://anytime-capital.com/api/v1/meter-events/batch \
      -H "Authorization: Bearer $ANYTIME_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "events": [
          {
            "eventName": "api_call",
            "customerId": "cus_1042",
            "idempotencyKey": "req_7f3a9d"
          },
          {
            "eventName": "api_call",
            "customerEmail": "jordan@example.com",
            "value": 3,
            "idempotencyKey": "req_7f3a9e"
          }
        ]
      }'
    const res = await fetch("https://anytime-capital.com/api/v1/meter-events/batch", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        events: [
          {
            eventName: "api_call",
            customerId: "cus_1042",
            idempotencyKey: "req_7f3a9d",
          },
          {
            eventName: "api_call",
            customerEmail: "jordan@example.com",
            value: 3,
            idempotencyKey: "req_7f3a9e",
          },
        ],
      }),
    });
    const result = await res.json();
    if (!res.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
    import os
    
    import requests
    
    res = requests.post(
        "https://anytime-capital.com/api/v1/meter-events/batch",
        headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
        json={
            "events": [
                {
                    "eventName": "api_call",
                    "customerId": "cus_1042",
                    "idempotencyKey": "req_7f3a9d",
                },
                {
                    "eventName": "api_call",
                    "customerEmail": "jordan@example.com",
                    "value": 3,
                    "idempotencyKey": "req_7f3a9e",
                },
            ],
        },
        timeout=30,
    )
    result = res.json()
    if not res.ok:
        raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}")
    Response 200
    {
      "object": "list",
      "data": [
        {
          "index": 0,
          "status": "created",
          "event": {
            "object": "meter_event",
            "livemode": true,
            "id": "mev_48214",
            "meter": "mtr_8fKq2LmNpR4sT6vW9xYz",
            "eventName": "api_call",
            "customer": "cus_1042",
            "customerEmail": "jordan@example.com",
            "value": "1",
            "timestamp": "2026-10-24T09:30:00.000Z",
            "idempotencyKey": "req_7f3a9d",
            "created": "2026-10-24T09:30:01.214Z"
          }
        },
        {
          "index": 1,
          "status": "refused",
          "error": {
            "code": "PERIOD_CLOSED",
            "message": "This customer's usage on API calls is already billed up to 2026-10-24T00:00:00.000Z. Send events from then on."
          }
        }
      ],
      "created": 1,
      "duplicates": 0,
      "refused": 1
    }

    Errors

    400INVALID_JSON
    The body isn't valid JSON, or couldn't be read. An empty body reads as {}. Send Content-Type: application/json and a JSON object.
    400INVALID_INPUT
    A field, filter, limit or cursor is missing or invalid. The message starts with the field's name, as in amountCents: …, or reads Invalid cursor. Fix the named field. Don't retry the same request unchanged.

    List meters

    GET/api/v1/meters
    Permission subscriptions:read

    The business's usage meters, newest first. Meters are made in the dashboard, on the Meters tab of Subscriptions.

    Query

    limit
    integer
    How many objects per page, 1–100. Default 25. See Pagination.
    cursor
    string
    The previous page's nextCursor, for the page after it.
    Request
    curl https://anytime-capital.com/api/v1/meters \
      -H "Authorization: Bearer $ANYTIME_API_KEY"
    const res = await fetch("https://anytime-capital.com/api/v1/meters", {
      headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
    });
    const page = await res.json();
    if (!res.ok) throw new Error(`${page.error.code}: ${page.error.message}`);
    import os
    
    import requests
    
    res = requests.get(
        "https://anytime-capital.com/api/v1/meters",
        headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
        timeout=30,
    )
    page = res.json()
    if not res.ok:
        raise RuntimeError(f"{page['error']['code']}: {page['error']['message']}")
    Response 200
    {
      "object": "list",
      "data": [
        {
          "object": "meter",
          "livemode": true,
          "id": "mtr_8fKq2LmNpR4sT6vW9xYz",
          "name": "API calls",
          "eventName": "api_call",
          "aggregation": "count",
          "unitLabel": "API call",
          "unitPriceCents": "0.25",
          "includedUnits": "1000",
          "status": "active",
          "createdAt": "2026-10-01T15:04:05.000Z"
        }
      ],
      "hasMore": false,
      "nextCursor": null
    }

    Errors

    400INVALID_INPUT
    A field, filter, limit or cursor is missing or invalid. The message starts with the field's name, as in amountCents: …, or reads Invalid cursor. Fix the named field. Don't retry the same request unchanged.

    Get a customer's usage

    GET/api/v1/meters/{id}/usage
    Permission subscriptions:read

    One customer's usage on a meter over a window (default the last 30 days, at most 366), with a daily breakdown. 422 CUSTOMER_HAS_NO_EMAIL when the customer has no email to match events by. Usage in [from, to) is added up the meter's way (sum, count, max or last), with one point per UTC day.

    Path

    id
    stringrequired
    mtr_…

    Query

    customerId
    string
    cus_…. Send this or customerEmail.
    customerEmail
    string
    The customer's email.
    from
    string
    Window start: a date (2026-10-01, midnight UTC) or an ISO 8601 date-time. Default: 30 days before to.
    to
    string
    Window end (exclusive), same format. Default: now. The window spans at most 366 days.
    Request
    curl "https://anytime-capital.com/api/v1/meters/mtr_8fKq2LmNpR4sT6vW9xYz/usage?customerId=cus_1042&from=2026-10-01&to=2026-10-03" \
      -H "Authorization: Bearer $ANYTIME_API_KEY"
    const res = await fetch("https://anytime-capital.com/api/v1/meters/mtr_8fKq2LmNpR4sT6vW9xYz/usage?customerId=cus_1042&from=2026-10-01&to=2026-10-03", {
      headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
    });
    const usage = await res.json();
    if (!res.ok) throw new Error(`${usage.error.code}: ${usage.error.message}`);
    import os
    
    import requests
    
    res = requests.get(
        "https://anytime-capital.com/api/v1/meters/mtr_8fKq2LmNpR4sT6vW9xYz/usage",
        headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
        params={"customerId": "cus_1042", "from": "2026-10-01", "to": "2026-10-03"},
        timeout=30,
    )
    usage = res.json()
    if not res.ok:
        raise RuntimeError(f"{usage['error']['code']}: {usage['error']['message']}")
    Response 200
    {
      "object": "meter_usage",
      "livemode": true,
      "meter": "mtr_8fKq2LmNpR4sT6vW9xYz",
      "customer": "cus_1042",
      "customerEmail": "jordan@example.com",
      "from": "2026-10-01T00:00:00.000Z",
      "to": "2026-10-03T00:00:00.000Z",
      "aggregation": "count",
      "quantity": "1210",
      "eventCount": 1210,
      "daily": [
        {
          "date": "2026-10-01",
          "quantity": "480"
        },
        {
          "date": "2026-10-02",
          "quantity": "730"
        }
      ]
    }

    Errors

    400INVALID_INPUT
    A field, filter, limit or cursor is missing or invalid. The message starts with the field's name, as in amountCents: …, or reads Invalid cursor. Fix the named field. Don't retry the same request unchanged.
    400CUSTOMER_MISMATCH
    customerId and customerEmail name different customers. Send one of them.
    404NOT_FOUND
    No such object on your business (an id from another business reads the same), or no such endpoint under /api/v1, which still answers in JSON. Check the id and the path. Ids are case-sensitive.
    422CUSTOMER_HAS_NO_EMAIL
    The customer has no email address, and usage is matched to subscriptions by email. Add an email to the customer in the dashboard, or send customerEmail.
    PreviousDiscount codesNext Payouts & balance

    Anytime Capital is a fintech company, not a bank. Payment processing, banking and payout services are provided by Anytime Capital's licensed partners. Rates shown are for US card payments; international cards, currency conversion and disputes may carry additional fees shown in your dashboard before you accept a payment.

    On this page

    • The meter object
    • The meter event object
    • The usage object
    • Endpoints
    • Record usage
    • Record usage in a batch
    • List meters
    • Get a customer's usage
    Anytime Capital
    (470) 748-2530
    App Store

    Business

    • Business Checking
    • Business Debit Cards
    • Payments
    • Ecommerce Payments
    • Invoicing
    • Developer Docs

    Solutions

    • CPAs & Accountants
    • Financial Advisors
    • Boat & Auto Dealerships
    • Dental & Medical Practices
    • Creators & Coaches
    • All solutions

    Crypto

    • Crypto Wallet
    • Tether Wallet
    • Buy Digital Assets
    • Explore Markets
    • Security & Licenses
    • Compare Platforms
    • Bitcoin ATM Alternative

    Company

    • Our Story
    • Schedule Appointment
    • Careers
    • Media & Press
    • Investor Relations
    • FAQ

    Branches

    • Atlanta, Georgia
    • Miami, Florida
    • Houston, Texas
    • All branches

    Legal

    • Terms & Conditions
    • Privacy Policy
    • Your Privacy Choices
    • Fraud Notice

    © 2026 Anytime Capital LLC. Anytime Capital is a fintech company, not a bank.

    The Anytime Capital Mastercard® Prepaid Card is issued by Pathward®, N.A., Member FDIC. Mastercard® is a registered trademark of Mastercard International Incorporated. All other trademarks and service marks belong to their respective owners.

    Mastercard