> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voyantcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Provider Invoice PDF

> Stream the provider-issued invoice PDF (SmartBill).

## Method

`GET` `/v1/billing/invoices/provider`

## Query Parameters

<ParamField query="series" type="string" required>Invoice series (e.g. `INV`).</ParamField>
<ParamField query="number" type="string" required>Invoice number inside the series.</ParamField>
<ParamField query="workspaceId" type="uuid">Workspace ID (optional if derived from API key).</ParamField>
<ParamField query="bookingId" type="uuid">Booking ID used to infer the provider when multiple are configured.</ParamField>
<ParamField query="provider" type="string">Provider hint (defaults to `smartbill`).</ParamField>

## Headers

<ParamField header="Authorization" type="string">Bearer token with `billing:read` scope.</ParamField>

## Request Example

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.voyantcloud.com/v1/billing/invoices/provider?series=INV&number=2025-00012&workspaceId=ws_abc" \
    -H "Authorization: Bearer $VOYANT_API_KEY" \
    -o invoice.pdf
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(
    "https://api.voyantcloud.com/v1/billing/invoices/provider?series=INV&number=2025-00012",
    { headers: { Authorization: `Bearer ${process.env.VOYANT_API_KEY}` } },
  )
  const buffer = await res.arrayBuffer()
  await fs.promises.writeFile("invoice.pdf", Buffer.from(buffer))
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.get(
    "https://api.voyantcloud.com/v1/billing/invoices/provider",
    params={"series": "INV", "number": "2025-00012", "workspaceId": "ws_abc"},
    headers={"Authorization": f"Bearer {os.environ['VOYANT_API_KEY']}"},
  )
  with open("invoice.pdf", "wb") as fh:
    fh.write(resp.content)
  ```
</RequestExample>

## Response

* **200 OK** – Binary PDF stream with `content-type: application/pdf` and `content-disposition: inline; filename=...`.
* **400 Bad Request** – Missing required parameters (`series`, `number`, or workspace context).
* **404 Not Found** – Workspace or provider configuration not found.
* **500 Internal Server Error** – KMS not configured or provider failure.

<Warning>This endpoint decrypts provider credentials using Google Cloud KMS. Ensure the environment is configured with `GCP_KMS_INTEGRATIONS_KEY_NAME` + access token, a service account key, or the fallback integrations KMS before calling it.</Warning>
