# Billing

Subscription, payment due, invoices and invoice PDFs, add-ons.

## Billing overview

`GET /billing` · scope `billing:read`

Subscription (state, plan, paid-until date, days left, payment method), unpaid state with the date sites are removed if it stays unpaid, site slots, add-ons, VAT treatment and the panel links.

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/billing" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/billing", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/billing", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": {
    "subscription": {
      "state": "active",
      "payment_method": "paypal",
      "paid_until": "2026-10-19T00:00:00Z",
      "expired": false,
      "days_left": 29,
      "trial": false,
      "next_plan": null,
      "pending_change": false,
      "cancelled": false,
      "staff_account": false,
      "plans": [
        {
          "name": "Standard",
          "slug": "standard",
          "sites_per_unit": 20,
          "units": 1,
          "sites": 20,
          "interval": "month",
          "trial": false,
          "price_usd": "49.00",
          "price_eur": "45.00",
          "price_gbp": "39.00"
        }
      ]
    },
    "slots": {
      "used": 12,
      "limit": 20
    },
    "addons": {},
    "vat": {
      "treatment": "reverse_charge",
      "rate_percent": "0",
      "country": "DE"
    },
    "invoices_url": "https://app.pbn.ltd/invoices/"
  }
}
```

Errors: `rate_limited`, `scope_missing`, `unauthorized`

## Payments and invoices

`GET /billing/invoices` · scope `billing:read`

Every payment and refund of the account, newest first. `document` is the invoice / credit note when one has been issued; download it with GET /billing/invoices/{number}.pdf.

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `limit` | query | integer | no | Items per page (1-200). Default: `50`. |
| `cursor` | query | string | no | The next_cursor value of the previous page. Omit for the first page. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/billing/invoices?limit=10" \
  -H "Authorization: Bearer $PBN_API_KEY"
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/billing/invoices?limit=10", headers=headers, timeout=120)
print(r.status_code, r.json())
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/billing/invoices?limit=10", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
```

### Response

`200`

```json
{
  "data": [
    {
      "key": "pp:I-ABC123",
      "date": "2026-09-01T10:00:00Z",
      "description": "Hosting plan (PayPal subscription)",
      "amount": "49.00",
      "currency": "USD",
      "kind": "payment",
      "seller": "pbn",
      "document": {
        "number": "PBN-2026-001234",
        "type": "invoice",
        "total": "49.00",
        "vat": "0.00",
        "net": "49.00",
        "issued_at": "2026-09-01T10:05:00Z",
        "pdf_api_url": "https://app.pbn.ltd/api/v1/billing/invoices/PBN-2026-001234.pdf",
        "pdf_panel_url": "https://app.pbn.ltd/invoices/PBN-2026-001234.pdf"
      }
    }
  ],
  "next_cursor": null,
  "has_more": false
}
```

Errors: `rate_limited`, `scope_missing`, `unauthorized`

## Download an invoice PDF

`GET /billing/invoices/{number}.pdf` · scope `billing:read`

The PDF of an invoice or credit note of this account (Content-Type application/pdf).

### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `number` | path | string | yes | Invoice number, e.g. PBN-2026-001234. |

### Example

```bash
curl -s "https://app.pbn.ltd/api/v1/billing/invoices/PBN-2026-001234.pdf" \
  -H "Authorization: Bearer $PBN_API_KEY" \
  -o invoice.pdf
```

```python
import os
import requests

headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/billing/invoices/PBN-2026-001234.pdf", headers=headers, timeout=120)
r.raise_for_status()
open("invoice.pdf", "wb").write(r.content)
```

```javascript
const res = await fetch("https://app.pbn.ltd/api/v1/billing/invoices/PBN-2026-001234.pdf", {
  method: "GET",
  headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
const pdf = Buffer.from(await res.arrayBuffer());  // Node 18+
```

### Response

`200` with the file (`application/pdf`).

Errors: `not_found`, `rate_limited`, `scope_missing`, `unauthorized`
