# Billing API

Read your monthly billing summary and outstanding invoices via the SDK.

HivePay charges merchants on a monthly cycle — see [Billing & Pricing](/payments/fees/) for the model. The SDK exposes one method merchants typically need: `billing.getMine()`.

---

## Get Your Billing Summary

Returns the current-month volume, the projected invoice at the prevailing tier, and the full history of outstanding and paid invoices.

+++ TypeScript
```typescript
import { HivePay } from '@hivepay/client';

const hivepay = new HivePay({ apiKey: process.env.HIVEPAY_API_KEY! });

const summary = await hivepay.billing.getMine();
```
+++ PHP
```php
use HivePay\HivePay;

$hivepay = new HivePay(['apiKey' => getenv('HIVEPAY_API_KEY')]);

$summary = $hivepay->billing->getMine();
```
+++ cURL
```bash
curl https://hivepay.me/api/public/billing/me \
  -H "Authorization: Bearer sk_live_xxx"
```
+++

---

## Response Shape

| Field | Type | Description |
|-------|------|-------------|
| `merchantId` | `string` | Your merchant ID |
| `merchantName` | `string` | Your business name |
| `currentMonth.periodStart` | `Date` / ISO string | UTC start of the current month |
| `currentMonth.periodEnd` | `Date` / ISO string | UTC start of the next month (exclusive) |
| `currentMonth.totalVolumeCents` | `number` | Volume processed this month, in USD cents |
| `currentMonth.transactionCount` | `number` | Completed transactions this month |
| `currentMonth.projectedInvoiceCents` | `number` | Projected month-end invoice at the prevailing tier |
| `outstandingInvoices` | `BillingPeriod[]` | Unpaid invoices (`invoiced` or `overdue`) |
| `paidInvoices` | `BillingPeriod[]` | Historical paid invoices |
| `outstandingAmountCents` | `number` | Sum of unpaid invoice amounts |
| `totalPaidCents` | `number` | Sum of all paid invoice amounts to date |
| `feeTiers` | `FeeTier[]` | Active tier schedule (sorted ascending by `minVolumeCents`) |

### BillingPeriod

| Field | Type | Description |
|-------|------|-------------|
| `id` | `string` | Unique billing period ID |
| `periodStart` | `Date` / ISO | First day of the billed month (UTC) |
| `periodEnd` | `Date` / ISO | First day of the next month (exclusive) |
| `totalVolumeCents` | `number` | Volume during the period (USD cents) |
| `transactionCount` | `number` | Completed transactions during the period |
| `invoiceAmountCents` | `number` | Invoice amount (USD cents) |
| `status` | `'open' \| 'invoiced' \| 'paid' \| 'overdue'` | Current status |
| `invoiceSessionId` | `string \| null` | Backing payment session ID |
| `invoiceSlug` | `string \| null` | Slug of the invoice session |
| `invoicePaymentUrl` | `string \| null` | Hosted URL to pay the invoice (only while unpaid) |

### FeeTier

| Field | Type | Description |
|-------|------|-------------|
| `minVolumeCents` | `number` | Inclusive lower bound (USD cents) |
| `maxVolumeCents` | `number \| null` | Inclusive upper bound, or `null` for the open-ended top tier |
| `percentFee` | `number` | Percentage rate for volume in this tier (e.g. `1.5` = 1.5%) |

---

## Pay an Outstanding Invoice

Outstanding invoices each include an `invoicePaymentUrl` — share or open it to pay in HBD via a regular HivePay checkout.

+++ TypeScript
```typescript
const summary = await hivepay.billing.getMine();

for (const invoice of summary.outstandingInvoices) {
  if (invoice.invoicePaymentUrl) {
    console.log(`Pay $${invoice.invoiceAmountCents / 100} at ${invoice.invoicePaymentUrl}`);
  }
}
```
+++ PHP
```php
$summary = $hivepay->billing->getMine();

foreach ($summary['outstandingInvoices'] as $invoice) {
    if ($invoice['invoicePaymentUrl']) {
        echo 'Pay $' . ($invoice['invoiceAmountCents'] / 100)
            . " at {$invoice['invoicePaymentUrl']}\n";
    }
}
```
+++

---

## Display the Active Tier Schedule

The schedule shipped with HivePay is configurable per deployment. Read `summary.feeTiers` rather than hard-coding rates so your app stays in sync if rates change.

+++ TypeScript
```typescript
const { feeTiers, currentMonth } = await hivepay.billing.getMine();

const sorted = [...feeTiers].sort((a, b) => a.minVolumeCents - b.minVolumeCents);
const currentTier = sorted.find(t =>
  currentMonth.totalVolumeCents >= t.minVolumeCents
  && (t.maxVolumeCents === null || currentMonth.totalVolumeCents <= t.maxVolumeCents)
);

if (currentTier) {
  console.log(`You are in the ${currentTier.percentFee}% tier this month.`);
}
```
+++

---

## Polling for Invoice Payment

After redirecting yourself to an `invoicePaymentUrl`, you can poll `getMine()` to confirm settlement — the period status flips from `invoiced` to `paid` as soon as the invoice transaction is confirmed on Hive.

+++ TypeScript
```typescript
import { HivePay } from '@hivepay/client';

const hivepay = new HivePay({ apiKey: process.env.HIVEPAY_API_KEY! });

async function waitForInvoicePaid (invoiceId: string, timeoutMs = 5 * 60 * 1000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const summary = await hivepay.billing.getMine();
    const paid = summary.paidInvoices.find(i => i.id === invoiceId);
    if (paid) return paid;

    await new Promise(r => setTimeout(r, 5000));
  }
  throw new Error('Invoice not paid within timeout');
}
```
+++

---

## Error Handling

`billing.getMine()` requires a valid merchant API key. Common errors:

| `error.code` | When |
|--------------|------|
| `AUTHENTICATION_ERROR` | Missing or invalid API key |
| `NETWORK_ERROR` | Network failure or timeout |
| `SERVER_ERROR` | Backend error (5xx) |

+++ TypeScript
```typescript
import { HivePay, isHivePayError } from '@hivepay/client';

try {
  const summary = await hivepay.billing.getMine();
  // ...
} catch (err) {
  if (isHivePayError(err) && err.isAuthError()) {
    console.error('Check your API key');
  } else {
    throw err;
  }
}
```
+++
