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

# External Costs

**External costs** bill third-party spend that Paygent doesn't track automatically — telephony minutes, SMS, shipping, human review, proprietary APIs, or any pass-through expense. You define cost categories and pricing rules in the dashboard, then report usage from your application with `send_external_cost`.

---

## How external billing works

```
Dashboard: External Cost → cost category + billing configs
        │
        ▼
Your app: send_external_cost(agent, customer, cost_data)
        │
        ▼
Paygent: match config → calculate amount → invoice line item
```

| Concept                      | Description                                                           |
| ---------------------------- | --------------------------------------------------------------------- |
| **External cost (category)** | Named bucket with an `externalCostId` (e.g. `telephony`)              |
| **Billing config**           | Pricing rule under a category — FLAT or PER_UNIT                      |
| **Usage event**              | SDK/API call with `name`, `externalCostId`, and optional `properties` |

---

## Step 1 — Create an external cost category

Sidebar → **External Cost** → **Add Cost**

| Field                | Description                                      |
| -------------------- | ------------------------------------------------ |
| **Cost name**        | Display name (e.g. "Telephony")                  |
| **External cost ID** | Unique key sent from your SDK (e.g. `telephony`) |
| **Description**      | Optional notes                                   |

The `externalCostId` must match `ExternalCostData.external_cost_id` in your integration.

---

## Step 2 — Add billing configurations

Expand a cost category → **Add Config**

| Field              | Description                                                         |
| ------------------ | ------------------------------------------------------------------- |
| **Name**           | Config identifier — must match `ExternalCostData.name` in SDK calls |
| **Billing type**   | `FLAT` (fixed per event) or `PER_UNIT` (rate × quantity)            |
| **Price**          | Base price or per-unit rate                                         |
| **Unit field(s)**  | For PER_UNIT: property keys to multiply (e.g. `duration_minutes`)   |
| **Property rates** | Per-key rates: `amount = Σ rate[k] × properties[k]`                 |
| **Currency**       | Line item currency                                                  |
| **Active**         | Inactive configs are ignored                                        |

### FLAT example

* Config name: `inbound_call`
* Billing type: FLAT
* Price: `$0.05` per call

Every matching event bills \$0.05 regardless of properties.

### PER_UNIT example

* Config name: `inbound_call`
* Billing type: PER_UNIT
* Price: `$0.02`
* Unit field: `duration_minutes`

Event with `properties: {"duration_minutes": 2.5}` → `$0.02 × 2.5 = $0.05`

### Multiple property rates

Set **property rates** when each key has its own rate:

```
propertyRates: { "minutes": 0.02, "sms_segments": 0.01 }
properties:    { "minutes": 3, "sms_segments": 2 }
→ $0.02×3 + $0.01×2 = $0.08
```

---

## Step 3 — Send usage from your application

#### Python

**`Track telephony cost`**

```python title="Track telephony cost"
import paygent_sdk
from paygent_sdk.models import ExternalCostData

paygent_sdk.init(api_key="your-paygent-api-key")

paygent_sdk.send_external_cost(
    agent_id="voice-agent",
    customer_id="customer-123",
    indicator="call-completed",  # optional — links to agent indicator
    cost_data=ExternalCostData(
        name="inbound_call",           # must match config name
        external_cost_id="telephony",  # must match cost category ID
        properties={"duration_minutes": 2.5},
        meta_tags={"region": "us-east"},
    ),
)
```

#### Node.js

**`Track external cost`**

```typescript title="Track external cost"
await client.sendExternalCost(
  'voice-agent',
  'customer-123',
  'call-completed',
  {
    name: 'inbound_call',
    externalCostId: 'telephony',
    properties: { duration_minutes: 2.5 },
    metaTags: { region: 'us-east' },
  }
);
```

### Required fields

| Field                        | Rule                                     |
| ---------------------------- | ---------------------------------------- |
| `agent_id`                   | Non-empty                                |
| `customer_id`                | Non-empty                                |
| `cost_data.name`             | Must match an active billing config name |
| `cost_data.external_cost_id` | Must match a cost category ID            |

Missing or unknown configs: the event is stored but may not generate revenue until a matching config exists.

---

## Error handling

The SDK validates required fields **synchronously** and raises `ValueError` if `agent_id`, `customer_id`, `name`, or `external_cost_id` is blank.

Network and API errors are logged asynchronously — `send_external_cost` is **fire-and-forget** and does not block your application. Wrap init calls in your own retry/monitoring if external costs are business-critical.

Invalid `meta_tags` are omitted with a warning; the cost event is still sent.

---

## External costs on invoices

When billing runs for an active order:

1. External cost events in the period are aggregated per config
2. Amounts appear as invoice line items alongside platform fees and usage
3. Taxes apply to the subtotal if configured on the order

View usage summaries in the dashboard under **External Cost** (date range + optional customer filter).

---

## Example: voice agent telephony pass-through

1. **External Cost** → category `telephony` / ID `telephony`
2. Config `inbound_call`: PER_UNIT, \$0.018/min, unit field `duration_minutes`
3. Config `outbound_call`: PER_UNIT, \$0.025/min, unit field `duration_minutes`
4. After each call, your telephony webhook calls `send_external_cost`
5. Monthly invoice includes telephony line items + AI usage from the same agent

---

## Checklist

* ✓ External cost category created with stable `externalCostId`
* ✓ Billing config(s) created with matching `name` and active status
* ✓ PER_UNIT: property keys in SDK match unit fields / property rates
* ✓ Active order exists for the customer
* ✓ SDK sends events with correct agent and customer IDs

**Related:** [Meta Tags](/documentation/meta-tags/event-meta-tags) · [Orders & Invoicing](/documentation/introduction/orders-and-invoicing) · [Error Handling](/documentation/guides/error-handling)