Claude Cursor Skill

cargo-billing

Understand what Cargo is costing — remaining credits, usage broken down by workflow, connector, or agent, subscription state, and invoice history. Triggers: "how many credits do I have left", "what did that cost", "why is my bill so high", "am I about to run out", "will this fit

LLM Mart · 0 points · 17 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download getcargohq-cargo-skills-cargo-billing-bb59f8d.zip · 11 KB
Part of getcargohq/cargo-skills — 22 skills

Install

skills CLI npx skills add https://github.com/getcargohq/cargo-skills/tree/main/cargo-billing
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install getcargohq-cargo-skills@llmmart
Git git clone https://github.com/getcargohq/cargo-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole getcargohq/cargo-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Cargo CLI — Billing

Billing and credit management: pulling usage metrics, checking subscription status, viewing invoices, and managing credits.

See references/response-shapes.md for full JSON response structures. See references/troubleshooting.md for common errors and how to fix them. See references/examples/usage-metrics.md for usage metric and subscription examples.

Bootstrap

Already signed in (cargo-ai whoami returns a workspace)? Skip to the next section.

npm install -g @cargo-ai/cli            # no global install? prefix every command with `npx @cargo-ai/cli`
cargo-ai login --email you@company.com  # emailed code, no browser; creates the account on first use
                                        # alternatives: --oauth (browser) · --token <api-token> (CI)
cargo-ai whoami                         # confirm the active workspace before any write

Every command prints JSON to stdout; failures exit non-zero with {"errorMessage": "..."}. Anything that creates a run or a batch is async — pass --wait-until-finished or poll the matching get. Admin-only: every command in this skill requires a token with admin access on the workspace. Non-admin tokens return {"errorMessage":"forbidden"}. When the full skill bundle is installed, ../cargo/references/prerequisites.md adds the CLI version pin, token scopes, and the admin-only surface.

Discover resources first

Usage metrics can be filtered and grouped by resource UUID. Discover them before querying.

cargo-ai orchestration play list            # all plays (name, workflowUuid)
cargo-ai orchestration tool list            # all tools (name, workflowUuid)
cargo-ai ai agent list                     # all agents (uuid, name)
cargo-ai connection connector list          # all connectors (uuid, name, integrationSlug)
cargo-ai storage model list                # all models (uuid, name, slug)

Quick reference

cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD>
cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD> --group-by workflow_uuid
cargo-ai billing subscription get
cargo-ai billing subscription get-invoices
cargo-ai billing subscription update-payment-method --card-number <number> --card-exp <MM/YYYY> --card-cvc <cvc>
cargo-ai billing subscription create-portal-session

Estimating cost before running a batch

Before triggering a large batch, estimate credit consumption to avoid unexpected charges.

Step 1 — Check current credit balance:

cargo-ai billing subscription get
# → subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount = remaining credits

Step 2 — Estimate cost from a sample run:

Run the workflow on a single record first and measure credits consumed:

# Run on one record
cargo-ai orchestration run create --workflow-uuid <uuid> --data '{...}'
# → poll to completion

# Check credits used for that run
cargo-ai billing usage get-metrics \
  --from <today> --to <today> \
  --workflow-uuid <uuid>
# → metrics[].items[] for that workflow (the response has one key, `metrics` — there is no `totalUsage`)

Step 3 — Project batch cost:

estimated_cost = (credits_per_record × number_of_records)      # provider actions
               + (nodes_per_record × number_of_records / 100)  # execution charge

The second term is the 0.01-credit-per-execution platform charge ("The execution charge" below). A sample run measures it for free — the record's execution count is length(run.executions), or one row of --unit orchestration.executions for the sample window. Leave it out and every step-heavy graph is under-quoted.

Compare against subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount before proceeding.

Step 4 — Monitor during the batch:

# Check running costs mid-batch
cargo-ai billing usage get-metrics \
  --from <start-date> --to <today> \
  --workflow-uuid <uuid>

Cost levers:

Action Effect
Use a cheaper model (e.g. gpt-4o-mini vs gpt-4o) Significant reduction for AI nodes
Add filter nodes early in the graph Skip ineligible records before expensive connector calls
Set fallbackOnFailure: false Stop the run early on failures instead of continuing to downstream nodes
Reduce maxSteps on agent nodes Limit how many tool calls an agent can make per record
Cut node count — collapse chained variables, fold branch pairs into one switch 0.01/execution × records; the only lever for a graph whose spend is steps, not providers

To find out which node or provider dominates a play's spend before picking a lever, follow the attribution runbook in ../cargo-diagnostics/references/play-optimize-credits.md.

Usage metrics

Pull credit and usage data for any time range, optionally filtered and grouped.

# Basic usage for a period
cargo-ai billing usage get-metrics --from <start-date> --to <end-date>

# Group by dimension
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by workflow_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by connector_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by integration_slug
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by model_uuid
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by agent_uuid

# Filter by specific resource
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --workflow-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --agent-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --connector-uuid <uuid>
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --integration-slug <slug>

# One unit at a time — the three below are the only accepted values
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit billing.credits
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit orchestration.executions
cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit storage.records

--group-by values: workflow_uuid, connector_uuid, model_uuid, integration_slug, agent_uuid.

Available filters: --workflow-uuid, --model-uuid, --connector-uuid, --integration-slug, --slug, --agent-uuid. Combine with --group-by and --unit.

The three usage units

--unit takes exactly billing.credits, orchestration.executions, or storage.records — anything else is a 400 that lists them. With no --unit, all three come back interleaved in the same items[] array, and their count fields are not the same quantity. Read the unit off the slug:

Unit Slugs in items[] What count is
billing.credits integration.<slug>.action.<action>, native.<action>, integration.<slug>.chat, integration.<slug>.extractor.<name> Credits (fractional)
orchestration.executions success, error Node executions, counted one-for-one — not credits
storage.records insert Records written

An unqualified call that shows {"slug":"success","count":1043} next to {"slug":"integration.peopleDataLabs.action.queryPeople","count":174} is reporting 1,043 executions beside 174 credits. Pass --unit whenever the number is going into an estimate.

The execution charge

Every node execution bills 0.01 credits — 1 credit per 100 executions. It applies to every node kind and every node, including the structural natives that carry no provider price: branch, filter, switch, split, group, variables, start, end. There is no free step in a workflow.

This charge is not attributed per node. run get → executions[].creditsUsedCount and the spans.execution_credits_used_count column both carry the provider cost alone, and read 0 on a native node that nonetheless billed. Node-by-node attribution therefore under-counts every graph, and the shortfall grows with step count, not with spend.

The only surface that shows it:

cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD> --unit orchestration.executions
# → items[] = [{"slug":"success","count":<executions>}, {"slug":"error","count":<executions>}]
# credits = (success + error) / 100

Cross-check against the runtime tables, which agree row-for-row:

cargo-ai orchestration query execute \
  "SELECT execution_status, count() AS executions, count() / 100 AS credits
   FROM spans WHERE execution_started_at >= '<YYYY-MM-DD>' GROUP BY execution_status"

Why it matters for estimates. A graph's cost has two terms:

credits = (provider cost per record × records) + (nodes per record × records ÷ 100)

The second term is invisible in the credits cost table, which prices actions, not steps. It is small next to an action-heavy play (a LinkedIn enrich on every record dwarfs its 8 steps) and dominant on step-heavy, action-light ones — a 12-node routing sweep over 20,000 records is 2,400 credits with no provider call at all. Errored executions bill too, so a graph that fails late bills its whole prefix.

Tools fan out. A tool node is one execution plus every node inside the tool's own graph, each billed separately. Extracting a subgraph into a tool is a debuggability win, not a cost saving — it adds one execution per record on top of what the internals already cost. When a graph's execution count exceeds its visible node count, tool nodes are the first place to look: group by node_slug in spans to find them.

Subscription and credits

cargo-ai billing subscription get                    # current plan, credits used/available, period dates
cargo-ai billing subscription get-invoices            # invoice history (amounts in cents)
cargo-ai billing subscription get-credit-card         # card on file
cargo-ai billing subscription update-payment-method   # add or replace the card (see below)
cargo-ai billing subscription create-portal-session   # Stripe portal URL for self-service billing

Remaining credits = subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount from subscription get.

Note: Invoice amounts are returned in cents. Divide by 100 for the dollar value.

The free tier

A new account starts with 100 free credits and no card on file. When subscription get shows a fresh or near-fresh balance, answer cost questions against that budget rather than as an abstract number — "you've used 12 of your 100 free credits" is the useful answer to "how am I doing?", and it is also the honest one when the user is deciding whether to keep going.

What 100 credits buys, as ballpark anchors (per-action costs in ../cargo-gtm/references/credits-cost-table.md):

Work Cost 100 credits ≈
Source leads — salesNavigator.searchLeads 0.02/record ~5,000 leads
Enrich from a LinkedIn URL + verified email — aiArk.enrichPerson 0.1 ~1,000 people
Verify an email — waterfall.verifyEmail 0.1 ~1,000 checks
Full contact enrichment — waterfall.enrichContact 2 ~50 contacts
Find a phone — FullEnrich.findPhone 6 ~16 numbers

The quickstart demo spends about 0.5. Phone lookups are the fastest way to burn a free tier, so phone is the guarded lever: the escalation tier runs 3–7 credits/record, ~10× email, and never belongs in a default chain — it enters a plan only on explicit user request, on qualified leads only. Full spend rules in ../cargo-gtm/references/cost-discipline.md.

Adding a card

A workspace holds exactly one card. update-payment-method sets it, whether or not one is already on file, and takes the details three ways.

# Card details — no browser, nothing to hand off
cargo-ai billing subscription update-payment-method \
  --card-number 4242424242424242 --card-exp 12/2030 --card-cvc 123

# Same, but keeps the number out of shell history and the process list
echo '{"number":"4242424242424242","expMonth":12,"expYear":2030,"cvc":"123"}' \
  | cargo-ai billing subscription update-payment-method --card-stdin

# No card details — prints a Stripe-hosted form URL and waits for the card to land
cargo-ai billing subscription update-payment-method

Prefer --card-stdin. Anything passed as a flag is visible in shell history and to any process that can read the process list. Card details go from your machine straight to Stripe in exchange for a token; they never reach the Cargo API, and no output prints them.

Never invent card details, and never reuse a number from elsewhere in the conversation. Ask the user for them, or use the no-argument form and hand them the URL.

The no-argument form is the fallback when you have no details to submit: it prints a URL that opens directly on the card form, then polls until the card changes (--timeout, --poll-interval, --no-open). Relay that URL to the user — it works over SSH and in sandboxes.

Either way the card is verified against the issuer before it becomes the default, so a card that cannot be charged fails here rather than silently at the next renewal.

Failure What it means What to do
cardDeclined + declineCode The issuer refused the verification Read declineCode. On a spend-limited virtual card, insufficient_funds or a limit code means the budget or merchant restrictions rule us out — ask the cardholder to raise it
authenticationRequired The card wants 3-D Secure, which needs the cardholder present Re-run with no arguments and hand the user the hosted-form URL
paymentMethodNotFound The details did not resolve to a usable card Re-check the number and expiry with the user

Card updates are rate-limited to 10 per hour per workspace (shared with setup intents). Retrying a declined card burns that budget — fix the cause rather than looping.

Help

Every command supports --help:

cargo-ai billing usage get-metrics --help
cargo-ai billing subscription get --help
cargo-ai billing subscription get-invoices --help
Files (cargo-skills)
  • references
    • examples
      • usage-metrics.md 5.3 KB
        # Usage metrics examples
        
        ## Get overall usage for a time range
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31
        ```
        
        Response:
        
        ```json
        {
          "metrics": [
            {
              "date": "2026-07-25T00:00:00.000Z",
              "items": [
                { "slug": "integration.peopleDataLabs.action.queryPeople", "count": 174, "groupBy": null },
                { "slug": "native.modelAsk", "count": 0.5, "groupBy": null },
                { "slug": "success", "count": 1043, "groupBy": null },
                { "slug": "error", "count": 32, "groupBy": null },
                { "slug": "insert", "count": 24, "groupBy": null }
              ]
            }
          ]
        }
        ```
        
        Each item has a `slug` (usage type) and `count`. When `--group-by` is used, `groupBy` contains the resource UUID/slug.
        
        **`count` is not always credits.** Unqualified, the array interleaves all three usage units: `integration.*` / `native.*` slugs are credits, `success` / `error` are **node executions** (credits = count / 100), `insert` is records written. Isolate one with `--unit billing.credits`, `--unit orchestration.executions`, or `--unit storage.records` — the only three accepted values.
        
        ## Isolate the execution charge
        
        Every node execution bills 0.01 credits, and it is attributed to no node — this is the only place it surfaces.
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2026-07-25 --to 2026-07-25 --unit orchestration.executions
        # → [{"slug":"error","count":32},{"slug":"success","count":1043}]
        # → 1,075 executions = 10.75 credits
        ```
        
        Same day, provider spend for comparison:
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2026-07-25 --to 2026-07-25 --unit billing.credits
        # → sum of items[].count = ~276 credits
        ```
        
        Here orchestration is ~4% because the day was action-heavy. On an action-light sweep the ratio inverts and executions become the largest line item. See [`../../SKILL.md`](../../SKILL.md) → "The execution charge".
        
        ## Group by workflow
        
        See which workflows consume the most credits.
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by workflow_uuid
        # → Each item has groupBy = workflow UUID
        # → Cross-reference with: cargo-ai orchestration workflow list
        ```
        
        ## Group by connector
        
        See which connectors (e.g. Salesforce, HubSpot) are used most.
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by connector_uuid
        # → Cross-reference with: cargo-ai connection connector list
        ```
        
        ## Group by integration
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by integration_slug
        ```
        
        ## Group by model
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by model_uuid
        # → Cross-reference with: cargo-ai storage model list
        ```
        
        ## Group by agent
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by agent_uuid
        # → Cross-reference with: cargo-ai ai agent list
        ```
        
        ## Filter usage to a specific workflow
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --workflow-uuid <uuid>
        ```
        
        ## Filter usage to a specific agent
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --agent-uuid <uuid>
        ```
        
        ## Filter usage to a specific connector
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --connector-uuid <uuid>
        ```
        
        ## Filter usage to a specific integration
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --integration-slug <slug>
        ```
        
        ## Specify unit (credits)
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --unit credits
        ```
        
        ## Combine group-by with filter
        
        Usage for a specific workflow, grouped by connector.
        
        ```bash
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --workflow-uuid <uuid> \
          --group-by connector_uuid
        ```
        
        ## Check subscription and remaining credits
        
        ```bash
        cargo-ai billing subscription get
        ```
        
        Response:
        
        ```json
        {
          "subscription": {
            "plan": "self-serve",
            "subscriptionStatus": "active",
            "subscriptionAvailableCreditsCount": 10000,
            "subscriptionCreditsUsedCount": 3200,
            "startAt": "2025-01-01T00:00:00Z",
            "resetAt": "2025-02-01T00:00:00Z"
          }
        }
        ```
        
        Remaining credits = `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount`.
        
        ```bash
        # Invoice history (amounts in cents — divide by 100 for dollars)
        cargo-ai billing subscription get-invoices
        
        # Card on file
        cargo-ai billing subscription get-credit-card
        
        # Open Stripe portal for self-service billing
        cargo-ai billing subscription create-portal-session
        ```
        
        ## Compare usage across two periods
        
        ```bash
        # This month
        cargo-ai billing usage get-metrics \
          --from 2025-02-01 --to 2025-02-28
        
        # Last month
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31
        
        # → Compare metrics[].items[].count values to spot trends
        ```
        
        ## Monthly usage report (full flow)
        
        ```bash
        # 1. Overall usage
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31
        
        # 2. Break down by workflow
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by workflow_uuid
        
        # 3. Break down by connector
        cargo-ai billing usage get-metrics \
          --from 2025-01-01 --to 2025-01-31 \
          --group-by connector_uuid
        
        # 4. Check remaining credits
        cargo-ai billing subscription get
        ```
        
    • response-shapes.md 4.6 KB
      # Response shapes
      
      JSON response structures returned by Cargo CLI commands used in the `cargo-billing` skill.
      
      ## cargo-ai billing usage get-metrics
      
      ```json
      {
        "metrics": [
          {
            "date": "2026-07-25T00:00:00.000Z",
            "items": [
              { "slug": "integration.peopleDataLabs.action.queryPeople", "count": 174, "groupBy": null },
              { "slug": "integration.serper.action.search", "count": 27.35, "groupBy": null },
              { "slug": "native.modelAsk", "count": 0.5, "groupBy": null },
              { "slug": "success", "count": 1043, "groupBy": null },
              { "slug": "error", "count": 32, "groupBy": null },
              { "slug": "insert", "count": 24, "groupBy": null }
            ]
          }
        ]
      }
      ```
      
      **With no `--unit`, three different quantities share one `items[]` array.** In the response above, `174` is credits, `1043` is *node executions*, and `24` is records written. Identify the unit from the slug:
      
      | Slug shape | Unit | `count` is |
      |---|---|---|
      | `integration.<slug>.action.<action>`, `integration.<slug>.chat`, `integration.<slug>.extractor.<name>`, `native.<action>` | `billing.credits` | Credits (fractional) |
      | `success`, `error` | `orchestration.executions` | Node executions — **credits = count / 100** |
      | `insert` | `storage.records` | Records written |
      
      `--unit` takes exactly `billing.credits`, `orchestration.executions`, or `storage.records`; any other value returns `400` listing those three. Pass it whenever the number feeds an estimate. The execution rows reconcile one-for-one with `SELECT execution_status, count() FROM spans` in `orchestration query execute`.
      
      When `--group-by` is specified, `groupBy` contains the resource identifier:
      
      ```json
      {
        "metrics": [
          {
            "date": "2025-01-15T00:00:00Z",
            "items": [
              { "slug": "enrichment", "count": 100, "groupBy": "workflow-uuid-1" },
              { "slug": "enrichment", "count": 50, "groupBy": "workflow-uuid-2" }
            ]
          }
        ]
      }
      ```
      
      **Key fields:** `metrics[].date`, `metrics[].items[].slug` (usage type), `metrics[].items[].count` (units depend on the slug — see above), `metrics[].items[].groupBy`.
      
      The response has exactly one top-level key, `metrics`. There is no `totalUsage` — sum `items[].count` yourself, within one unit.
      
      ## cargo-ai billing subscription get
      
      ```json
      {
        "subscription": {
          "uuid": "...",
          "workspaceUuid": "...",
          "plan": "self-serve",
          "cadence": "monthly",
          "subscriptionStatus": "active",
          "subscriptionAvailableCreditsCount": 10000,
          "subscriptionCreditsUsedCount": 3200,
          "additionalAvailableCreditsCount": 0,
          "fixedPrice": 9900,
          "conversionRate": 1,
          "hasCredits": true,
          "startAt": "2025-01-01T00:00:00Z",
          "resetAt": "2025-02-01T00:00:00Z",
          "endAt": null,
          "topup": null,
          "createdAt": "2025-01-01T00:00:00Z",
          "updatedAt": "2025-01-15T00:00:00Z"
        }
      }
      ```
      
      **Key fields:** `plan` (`self-serve` or `enterprise`), `subscriptionStatus`, `subscriptionAvailableCreditsCount`, `subscriptionCreditsUsedCount`, `startAt`, `resetAt`.
      
      Remaining credits = `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount`.
      
      ## cargo-ai billing subscription get-invoices
      
      ```json
      {
        "invoices": [
          {
            "id": "inv_...",
            "isPaid": true,
            "amount": 9900,
            "currency": "usd",
            "dueDate": "2025-02-01T00:00:00Z",
            "url": "https://..."
          }
        ]
      }
      ```
      
      **Key fields:** `id`, `isPaid` (boolean), `amount` (in cents — divide by 100 for dollars, e.g. `9900` = $99.00), `url` (link to the invoice).
      
      ## cargo-ai billing subscription create-portal-session
      
      ```json
      {
        "portalSession": {
          "url": "https://billing.stripe.com/session/..."
        }
      }
      ```
      
      Open `portalSession.url` in a browser to access the Stripe self-service billing portal.
      
      ## cargo-ai billing subscription update-payment-method
      
      ```json
      {
        "ok": true,
        "status": "updated",
        "creditCard": {
          "brand": "visa",
          "last4": "4242",
          "expMonth": 12,
          "expYear": 2030
        }
      }
      ```
      
      **Key fields:** `creditCard` describes the card now on file — the only card data ever returned. `creditCard` is absent if the card could not be read back straight after the update; the update still succeeded.
      
      On failure the command exits non-zero with `{"errorMessage": "..."}` plus a `reason` of `cardDeclined`, `authenticationRequired`, or `paymentMethodNotFound`. A `cardDeclined` carries the issuer's `declineCode` — see [`troubleshooting.md`](troubleshooting.md).
      
      ## cargo-ai billing subscription get-credit-card
      
      ```json
      {
        "creditCard": {
          "brand": "visa",
          "last4": "4242",
          "expMonth": 12,
          "expYear": 2030
        }
      }
      ```
      
      `creditCard` is `undefined` when no card is on file — the normal state for a workspace still on the free tier.
      
    • troubleshooting.md 3.1 KB
      # Troubleshooting
      
      Common errors and recovery steps for `cargo-billing` commands.
      
      ## General
      
      | Symptom | Cause | Fix |
      |---------|-------|-----|
      | `{"errorMessage": "..."}` with non-zero exit | Any CLI error | Read the `errorMessage` — it usually says exactly what's wrong |
      | `command not found: cargo-ai` | CLI not installed or not in PATH | Run `npm install -g @cargo-ai/cli` or prefix with `npx @cargo-ai/cli` |
      | `Unauthorized` or `Forbidden` | Bad or expired credentials | Re-run `cargo-ai login --oauth` (browser sign-in) or `cargo-ai login --token <token>`; verify with `cargo-ai whoami` |
      
      ## Usage metrics
      
      | Symptom | Cause | Fix |
      |---------|-------|-----|
      | Empty metrics (no items) | Date range has no activity, or wrong format | Verify dates are `YYYY-MM-DD`; try a wider range; confirm the workspace had activity in that period |
      | `--group-by` returns items with null `groupBy` | Some usage isn't attributable to that dimension | This is expected — unattributed usage shows `groupBy: null` |
      | Metrics don't match expectations | Filtering by wrong resource UUID | Re-discover UUIDs with `play list`, `tool list`, `connector list`, or `agent list` |
      
      ## Subscription and billing
      
      | Symptom | Cause | Fix |
      |---------|-------|-----|
      | `subscription get` returns `Forbidden` | Token lacks billing permissions | Use a token with admin access; check workspace settings under **Settings > API** |
      | Invoice amounts look wrong | Amounts are in cents, not dollars | Divide `amount` by 100 for the dollar value |
      | `create-portal-session` returns an error | Subscription not active or no Stripe setup | Verify the workspace has an active paid subscription |
      
      ## Adding a card
      
      | Symptom | Cause | Fix |
      |---------|-------|-----|
      | `cardDeclined` with a `declineCode` | The issuer refused the zero-amount verification | Read `declineCode`. On a spend-limited virtual card this usually means the budget or merchant restrictions exclude us — ask the cardholder to raise the limit, then retry |
      | `authenticationRequired` | The card requires 3-D Secure, which cannot be completed without the cardholder | Re-run `update-payment-method` with no arguments and give the user the hosted-form URL |
      | `paymentMethodNotFound` | The details did not resolve to a card we can use | Re-check the number and expiry with the user |
      | `Rate limit exceeded` on `update-payment-method` | More than 10 card updates in an hour for this workspace | Wait for `retryAfter`. Repeatedly retrying a declined card is what exhausts this — fix the decline cause first |
      | Stripe rejects the card before Cargo sees it (`code`, `param` in the error) | The number, expiry, or CVC is malformed | The `param` field names the bad field; correct it with the user |
      | `no Stripe publishable key configured` | The Cargo environment is missing `STRIPE_PUBLIC_KEY` | Environment misconfiguration, not a user error — report it; the hosted-form flow (no arguments) still works |
      | Hosted form times out | Nobody completed the form in the window | Re-run with a longer `--timeout`, or confirm with `get-credit-card` — the card may have landed after the wait ended |
      
  • skill-metadata.json 792 B
    {
      "$comment": "Generated by .github/scripts/skills-metadata.mjs — do not hand-edit. Regenerate with: node .github/scripts/skills-metadata.mjs --write .",
      "name": "cargo-billing",
      "version": "2.0.0",
      "documents": [
        {
          "path": "SKILL.md",
          "kind": "entrypoint",
          "title": "Cargo CLI — Billing"
        },
        {
          "path": "references/examples/usage-metrics.md",
          "kind": "example",
          "title": "Usage metrics examples"
        },
        {
          "path": "references/response-shapes.md",
          "kind": "reference",
          "title": "Response shapes"
        },
        {
          "path": "references/troubleshooting.md",
          "kind": "reference",
          "title": "Troubleshooting"
        }
      ],
      "contentHash": "d5e316090aed9cd788411c1d58738f0076e1263bdfd881110fb7ad75268270d6"
    }
    
  • SKILL.md 15.4 KB
    ---
    name: cargo-billing
    description: "Understand what Cargo is costing — remaining credits, usage broken down by workflow, connector, or agent, subscription state, and invoice history. Triggers: \"how many credits do I have left\", \"what did that cost\", \"why is my bill so high\", \"am I about to run out\", \"will this fit in our budget\", \"show me my invoices\", \"how much have I spent this month\", \"what plan am I on\", \"what do I get for free\", \"how many free credits\", \"can I afford this run\", \"add a card\", \"update my payment method\", \"why was my card declined\". Needs a token with admin access. Skip when: attributing spend to specific nodes or cutting a play cost — use cargo-diagnostics."
    version: "2.0.0"
    compatibility: Requires @cargo-ai/cli (npm). Sign in or create an account with `cargo-ai login --email` (emailed code, no browser), `--oauth`, or an API token
    homepage: https://github.com/getcargohq/cargo-skills
    metadata:
      author: getcargo
      openclaw:
        requires:
          bins:
            - cargo-ai
        install:
          - kind: node
            package: "@cargo-ai/cli@latest"
            bins:
              - cargo-ai
        homepage: https://github.com/getcargohq/cargo-skills
    ---
    
    # Cargo CLI — Billing
    
    Billing and credit management: pulling usage metrics, checking subscription status, viewing invoices, and managing credits.
    
    > See `references/response-shapes.md` for full JSON response structures.
    > See `references/troubleshooting.md` for common errors and how to fix them.
    > See `references/examples/usage-metrics.md` for usage metric and subscription examples.
    
    ## Bootstrap
    
    Already signed in (`cargo-ai whoami` returns a workspace)? Skip to the next section.
    
    ```bash
    npm install -g @cargo-ai/cli            # no global install? prefix every command with `npx @cargo-ai/cli`
    cargo-ai login --email you@company.com  # emailed code, no browser; creates the account on first use
                                            # alternatives: --oauth (browser) · --token <api-token> (CI)
    cargo-ai whoami                         # confirm the active workspace before any write
    ```
    
    Every command prints JSON to stdout; failures exit non-zero with `{"errorMessage": "..."}`. Anything that creates a run or a batch is async — pass `--wait-until-finished` or poll the matching `get`. **Admin-only:** every command in this skill requires a token with admin access on the workspace. Non-admin tokens return `{"errorMessage":"forbidden"}`. When the full skill bundle is installed, [`../cargo/references/prerequisites.md`](../cargo/references/prerequisites.md) adds the CLI version pin, token scopes, and the admin-only surface.
    
    ## Discover resources first
    
    Usage metrics can be filtered and grouped by resource UUID. Discover them before querying.
    
    ```bash
    cargo-ai orchestration play list            # all plays (name, workflowUuid)
    cargo-ai orchestration tool list            # all tools (name, workflowUuid)
    cargo-ai ai agent list                     # all agents (uuid, name)
    cargo-ai connection connector list          # all connectors (uuid, name, integrationSlug)
    cargo-ai storage model list                # all models (uuid, name, slug)
    ```
    
    ## Quick reference
    
    ```bash
    cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD>
    cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD> --group-by workflow_uuid
    cargo-ai billing subscription get
    cargo-ai billing subscription get-invoices
    cargo-ai billing subscription update-payment-method --card-number <number> --card-exp <MM/YYYY> --card-cvc <cvc>
    cargo-ai billing subscription create-portal-session
    ```
    
    ## Estimating cost before running a batch
    
    Before triggering a large batch, estimate credit consumption to avoid unexpected charges.
    
    **Step 1 — Check current credit balance:**
    
    ```bash
    cargo-ai billing subscription get
    # → subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount = remaining credits
    ```
    
    **Step 2 — Estimate cost from a sample run:**
    
    Run the workflow on a single record first and measure credits consumed:
    
    ```bash
    # Run on one record
    cargo-ai orchestration run create --workflow-uuid <uuid> --data '{...}'
    # → poll to completion
    
    # Check credits used for that run
    cargo-ai billing usage get-metrics \
      --from <today> --to <today> \
      --workflow-uuid <uuid>
    # → metrics[].items[] for that workflow (the response has one key, `metrics` — there is no `totalUsage`)
    ```
    
    **Step 3 — Project batch cost:**
    
    ```
    estimated_cost = (credits_per_record × number_of_records)      # provider actions
                   + (nodes_per_record × number_of_records / 100)  # execution charge
    ```
    
    The second term is the 0.01-credit-per-execution platform charge ("The execution charge" below). A sample run measures it for free — the record's execution count is `length(run.executions)`, or one row of `--unit orchestration.executions` for the sample window. Leave it out and every step-heavy graph is under-quoted.
    
    Compare against `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount` before proceeding.
    
    **Step 4 — Monitor during the batch:**
    
    ```bash
    # Check running costs mid-batch
    cargo-ai billing usage get-metrics \
      --from <start-date> --to <today> \
      --workflow-uuid <uuid>
    ```
    
    **Cost levers:**
    
    | Action | Effect |
    |---|---|
    | Use a cheaper model (e.g. `gpt-4o-mini` vs `gpt-4o`) | Significant reduction for AI nodes |
    | Add `filter` nodes early in the graph | Skip ineligible records before expensive connector calls |
    | Set `fallbackOnFailure: false` | Stop the run early on failures instead of continuing to downstream nodes |
    | Reduce `maxSteps` on agent nodes | Limit how many tool calls an agent can make per record |
    | Cut node count — collapse chained `variables`, fold branch pairs into one `switch` | 0.01/execution × records; the only lever for a graph whose spend is steps, not providers |
    
    > To find out **which** node or provider dominates a play's spend before picking a lever, follow the attribution runbook in [`../cargo-diagnostics/references/play-optimize-credits.md`](../cargo-diagnostics/references/play-optimize-credits.md).
    
    ## Usage metrics
    
    Pull credit and usage data for any time range, optionally filtered and grouped.
    
    ```bash
    # Basic usage for a period
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date>
    
    # Group by dimension
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by workflow_uuid
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by connector_uuid
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by integration_slug
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by model_uuid
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --group-by agent_uuid
    
    # Filter by specific resource
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --workflow-uuid <uuid>
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --agent-uuid <uuid>
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --connector-uuid <uuid>
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --integration-slug <slug>
    
    # One unit at a time — the three below are the only accepted values
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit billing.credits
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit orchestration.executions
    cargo-ai billing usage get-metrics --from <start-date> --to <end-date> --unit storage.records
    ```
    
    `--group-by` values: `workflow_uuid`, `connector_uuid`, `model_uuid`, `integration_slug`, `agent_uuid`.
    
    Available filters: `--workflow-uuid`, `--model-uuid`, `--connector-uuid`, `--integration-slug`, `--slug`, `--agent-uuid`. Combine with `--group-by` and `--unit`.
    
    ### The three usage units
    
    `--unit` takes exactly `billing.credits`, `orchestration.executions`, or `storage.records` — anything else is a `400` that lists them. **With no `--unit`, all three come back interleaved in the same `items[]` array**, and their `count` fields are not the same quantity. Read the unit off the slug:
    
    | Unit | Slugs in `items[]` | What `count` is |
    |---|---|---|
    | `billing.credits` | `integration.<slug>.action.<action>`, `native.<action>`, `integration.<slug>.chat`, `integration.<slug>.extractor.<name>` | Credits (fractional) |
    | `orchestration.executions` | `success`, `error` | **Node executions**, counted one-for-one — not credits |
    | `storage.records` | `insert` | Records written |
    
    An unqualified call that shows `{"slug":"success","count":1043}` next to `{"slug":"integration.peopleDataLabs.action.queryPeople","count":174}` is reporting 1,043 *executions* beside 174 *credits*. Pass `--unit` whenever the number is going into an estimate.
    
    ### The execution charge
    
    **Every node execution bills 0.01 credits — 1 credit per 100 executions.** It applies to every node kind and every node, including the structural natives that carry no provider price: `branch`, `filter`, `switch`, `split`, `group`, `variables`, `start`, `end`. There is no free step in a workflow.
    
    This charge is **not attributed per node**. `run get` → `executions[].creditsUsedCount` and the `spans.execution_credits_used_count` column both carry the *provider* cost alone, and read `0` on a native node that nonetheless billed. Node-by-node attribution therefore under-counts every graph, and the shortfall grows with step count, not with spend.
    
    The only surface that shows it:
    
    ```bash
    cargo-ai billing usage get-metrics --from <YYYY-MM-DD> --to <YYYY-MM-DD> --unit orchestration.executions
    # → items[] = [{"slug":"success","count":<executions>}, {"slug":"error","count":<executions>}]
    # credits = (success + error) / 100
    ```
    
    Cross-check against the runtime tables, which agree row-for-row:
    
    ```bash
    cargo-ai orchestration query execute \
      "SELECT execution_status, count() AS executions, count() / 100 AS credits
       FROM spans WHERE execution_started_at >= '<YYYY-MM-DD>' GROUP BY execution_status"
    ```
    
    **Why it matters for estimates.** A graph's cost has two terms:
    
    ```
    credits = (provider cost per record × records) + (nodes per record × records ÷ 100)
    ```
    
    The second term is invisible in the credits cost table, which prices *actions*, not *steps*. It is small next to an action-heavy play (a LinkedIn enrich on every record dwarfs its 8 steps) and dominant on step-heavy, action-light ones — a 12-node routing sweep over 20,000 records is 2,400 credits with no provider call at all. Errored executions bill too, so a graph that fails late bills its whole prefix.
    
    **Tools fan out.** A tool node is one execution *plus* every node inside the tool's own graph, each billed separately. Extracting a subgraph into a tool is a debuggability win, not a cost saving — it adds one execution per record on top of what the internals already cost. When a graph's execution count exceeds its visible node count, tool nodes are the first place to look: group by `node_slug` in `spans` to find them.
    
    ## Subscription and credits
    
    ```bash
    cargo-ai billing subscription get                    # current plan, credits used/available, period dates
    cargo-ai billing subscription get-invoices            # invoice history (amounts in cents)
    cargo-ai billing subscription get-credit-card         # card on file
    cargo-ai billing subscription update-payment-method   # add or replace the card (see below)
    cargo-ai billing subscription create-portal-session   # Stripe portal URL for self-service billing
    ```
    
    Remaining credits = `subscriptionAvailableCreditsCount - subscriptionCreditsUsedCount` from `subscription get`.
    
    **Note:** Invoice amounts are returned in cents. Divide by 100 for the dollar value.
    
    ### The free tier
    
    A new account starts with **100 free credits and no card on file**. When `subscription get` shows a fresh or near-fresh balance, answer cost questions against that budget rather than as an abstract number — "you've used 12 of your 100 free credits" is the useful answer to "how am I doing?", and it is also the honest one when the user is deciding whether to keep going.
    
    What 100 credits buys, as ballpark anchors (per-action costs in [`../cargo-gtm/references/credits-cost-table.md`](../cargo-gtm/references/credits-cost-table.md)):
    
    | Work | Cost | 100 credits ≈ |
    |---|---|---|
    | Source leads — `salesNavigator.searchLeads` | 0.02/record | ~5,000 leads |
    | Enrich from a LinkedIn URL + verified email — `aiArk.enrichPerson` | 0.1 | ~1,000 people |
    | Verify an email — `waterfall.verifyEmail` | 0.1 | ~1,000 checks |
    | Full contact enrichment — `waterfall.enrichContact` | 2 | ~50 contacts |
    | Find a phone — `FullEnrich.findPhone` | 6 | ~16 numbers |
    
    The [quickstart demo](../cargo-quickstart/SKILL.md) spends about **0.5**. Phone lookups are the fastest way to burn a free tier, so phone is the **guarded lever**: the escalation tier runs 3–7 credits/record, ~10× email, and never belongs in a default chain — it enters a plan only on explicit user request, on qualified leads only. Full spend rules in [`../cargo-gtm/references/cost-discipline.md`](../cargo-gtm/references/cost-discipline.md).
    
    ### Adding a card
    
    A workspace holds exactly one card. `update-payment-method` sets it, whether or not one is already on file, and takes the details three ways.
    
    ```bash
    # Card details — no browser, nothing to hand off
    cargo-ai billing subscription update-payment-method \
      --card-number 4242424242424242 --card-exp 12/2030 --card-cvc 123
    
    # Same, but keeps the number out of shell history and the process list
    echo '{"number":"4242424242424242","expMonth":12,"expYear":2030,"cvc":"123"}' \
      | cargo-ai billing subscription update-payment-method --card-stdin
    
    # No card details — prints a Stripe-hosted form URL and waits for the card to land
    cargo-ai billing subscription update-payment-method
    ```
    
    **Prefer `--card-stdin`.** Anything passed as a flag is visible in shell history and to any process that can read the process list. Card details go from your machine straight to Stripe in exchange for a token; they never reach the Cargo API, and no output prints them.
    
    **Never invent card details, and never reuse a number from elsewhere in the conversation.** Ask the user for them, or use the no-argument form and hand them the URL.
    
    The no-argument form is the fallback when you have no details to submit: it prints a URL that opens directly on the card form, then polls until the card changes (`--timeout`, `--poll-interval`, `--no-open`). Relay that URL to the user — it works over SSH and in sandboxes.
    
    Either way the card is verified against the issuer before it becomes the default, so a card that cannot be charged fails here rather than silently at the next renewal.
    
    | Failure | What it means | What to do |
    |---|---|---|
    | `cardDeclined` + `declineCode` | The issuer refused the verification | Read `declineCode`. On a spend-limited virtual card, `insufficient_funds` or a limit code means the budget or merchant restrictions rule us out — ask the cardholder to raise it |
    | `authenticationRequired` | The card wants 3-D Secure, which needs the cardholder present | Re-run with no arguments and hand the user the hosted-form URL |
    | `paymentMethodNotFound` | The details did not resolve to a usable card | Re-check the number and expiry with the user |
    
    Card updates are rate-limited to **10 per hour per workspace** (shared with setup intents). Retrying a declined card burns that budget — fix the cause rather than looping.
    
    ## Help
    
    Every command supports `--help`:
    
    ```bash
    cargo-ai billing usage get-metrics --help
    cargo-ai billing subscription get --help
    cargo-ai billing subscription get-invoices --help
    ```
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related