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

# Get Invoices

> Get a list of billing invoices for the authenticated user

## Endpoint

```
GET https://www.wiseyield.co/api/billing/invoices
```

## Authentication

Requires a valid API key with `billing:read` scope.

## Response

Returns an array of invoice objects (max 10 most recent).

<ResponseField name="invoices" type="array">
  <Expandable title="Invoice Object">
    <ResponseField name="id" type="string">
      Unique invoice ID
    </ResponseField>

    <ResponseField name="userId" type="string">
      User ID who owns this invoice
    </ResponseField>

    <ResponseField name="paymentId" type="string">
      Dodo Payments payment ID
    </ResponseField>

    <ResponseField name="customerId" type="string">
      Dodo Payments customer ID
    </ResponseField>

    <ResponseField name="subscriptionId" type="string">
      Associated subscription ID (if applicable)
    </ResponseField>

    <ResponseField name="amount" type="number">
      Invoice amount in cents (e.g., 8900 = €89.00)
    </ResponseField>

    <ResponseField name="currency" type="string">
      Currency code (e.g., `usd`, `eur`)
    </ResponseField>

    <ResponseField name="status" type="string">
      Invoice status: `paid`, `open`, `void`, `uncollectible`
    </ResponseField>

    <ResponseField name="invoiceUrl" type="string">
      URL to view/download invoice PDF
    </ResponseField>

    <ResponseField name="invoiceNumber" type="string">
      Human-readable invoice number (e.g., `INV-0001`)
    </ResponseField>

    <ResponseField name="periodStart" type="string">
      ISO 8601 datetime when billing period started
    </ResponseField>

    <ResponseField name="periodEnd" type="string">
      ISO 8601 datetime when billing period ended
    </ResponseField>

    <ResponseField name="paidAt" type="string">
      ISO 8601 datetime when invoice was paid (null if unpaid)
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 datetime when invoice was created
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET https://www.wiseyield.co/api/billing/invoices \
    -H "Authorization: Bearer wy_YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://www.wiseyield.co/api/billing/invoices',
    {
      headers: {
        'Authorization': 'Bearer wy_YOUR_API_KEY'
      }
    }
  );

  const { invoices } = await response.json();
  console.log(`${invoices.length} invoices found`);

  invoices.forEach(invoice => {
    console.log(`${invoice.invoiceNumber}: €${invoice.amount / 100} - ${invoice.status}`);
  });
  ```

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

  response = requests.get(
      'https://www.wiseyield.co/api/billing/invoices',
      headers={'Authorization': 'Bearer wy_YOUR_API_KEY'}
  )

  data = response.json()
  invoices = data['invoices']

  for invoice in invoices:
      amount = invoice['amount'] / 100
      print(f"{invoice['invoiceNumber']}: €{amount:.2f} - {invoice['status']}")
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Success (With Invoices) theme={null}
  {
    "invoices": [
      {
        "id": "inv_abc123",
        "userId": "user_xyz789",
        "paymentId": "in_1234567890",
        "customerId": "cus_9876543210",
        "subscriptionId": "sub_abc123",
        "amount": 8900,
        "currency": "eur",
        "status": "paid",
        "invoiceUrl": "https://payments.dodopayments.com/invoices/inv_...",
        "invoiceNumber": "INV-0042",
        "periodStart": "2025-11-01T00:00:00.000Z",
        "periodEnd": "2025-12-01T00:00:00.000Z",
        "paidAt": "2025-11-01T10:05:00.000Z",
        "createdAt": "2025-11-01T10:00:00.000Z"
      },
      {
        "id": "inv_def456",
        "userId": "user_xyz789",
        "paymentId": "in_0987654321",
        "customerId": "cus_9876543210",
        "subscriptionId": "sub_abc123",
        "amount": 8900,
        "currency": "eur",
        "status": "paid",
        "invoiceUrl": "https://payments.dodopayments.com/invoices/inv_...",
        "invoiceNumber": "INV-0041",
        "periodStart": "2025-10-01T00:00:00.000Z",
        "periodEnd": "2025-11-01T00:00:00.000Z",
        "paidAt": "2025-10-01T10:05:00.000Z",
        "createdAt": "2025-10-01T10:00:00.000Z"
      }
    ]
  }
  ```

  ```json 200 Success (No Invoices) theme={null}
  {
    "invoices": []
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": "Unauthorized"
  }
  ```

  ```json 500 Internal Server Error theme={null}
  {
    "error": "Failed to fetch invoices"
  }
  ```
</ResponseExample>

## Errors

<ResponseField name="401" type="error">
  Unauthorized - Missing or invalid API key
</ResponseField>

<ResponseField name="500" type="error">
  Internal Server Error - Failed to fetch invoices
</ResponseField>

## Invoice Statuses

<ParamField name="paid" type="status">
  Invoice has been paid successfully
</ParamField>

<ParamField name="open" type="status">
  Invoice awaiting payment (pending)
</ParamField>

<ParamField name="void" type="status">
  Invoice has been voided/canceled
</ParamField>

<ParamField name="uncollectible" type="status">
  Payment failed after multiple attempts, marked uncollectible
</ParamField>

## Limits

**Response Limit**: Returns maximum 10 most recent invoices, ordered by `createdAt` descending.

**Time Range**: No time limit - returns all historical invoices up to the limit.

## Use Cases

### Display Invoice History

```javascript theme={null}
async function getInvoiceHistory() {
  const response = await fetch('/api/billing/invoices', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const { invoices } = await response.json();

  return invoices.map(invoice => ({
    id: invoice.id,
    number: invoice.invoiceNumber,
    amount: `€${(invoice.amount / 100).toFixed(2)}`,
    status: invoice.status,
    date: new Date(invoice.createdAt).toLocaleDateString(),
    downloadUrl: invoice.invoiceUrl
  }));
}

// Usage
const history = await getInvoiceHistory();
console.table(history);
```

### Check Last Payment

```javascript theme={null}
async function getLastPayment() {
  const response = await fetch('/api/billing/invoices', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const { invoices } = await response.json();

  const paidInvoices = invoices.filter(inv => inv.status === 'paid');

  if (paidInvoices.length === 0) {
    return null;
  }

  const latest = paidInvoices[0]; // Already sorted by createdAt desc

  return {
    amount: latest.amount / 100,
    date: new Date(latest.paidAt),
    invoiceNumber: latest.invoiceNumber
  };
}

// Usage
const lastPayment = await getLastPayment();
if (lastPayment) {
  console.log(`Last payment: €${lastPayment.amount} on ${lastPayment.date.toLocaleDateString()}`);
}
```

### Calculate Total Spent

```javascript theme={null}
async function getTotalSpent() {
  const response = await fetch('/api/billing/invoices', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const { invoices } = await response.json();

  const total = invoices
    .filter(inv => inv.status === 'paid')
    .reduce((sum, inv) => sum + inv.amount, 0);

  return total / 100; // Convert cents to euros
}

// Usage
const totalSpent = await getTotalSpent();
console.log(`Total spent: €${totalSpent.toFixed(2)}`);
```

### Check for Unpaid Invoices

```javascript theme={null}
async function hasUnpaidInvoices() {
  const response = await fetch('/api/billing/invoices', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const { invoices } = await response.json();

  const unpaid = invoices.filter(inv => inv.status === 'open');

  return {
    hasUnpaid: unpaid.length > 0,
    count: unpaid.length,
    unpaidInvoices: unpaid
  };
}

// Usage
const { hasUnpaid, count, unpaidInvoices } = await hasUnpaidInvoices();
if (hasUnpaid) {
  console.log(`You have ${count} unpaid invoice(s)`);
}
```

## Best Practices

<Tip>
  **Display Currency**: Always format `amount` by dividing by 100 and showing currency symbol.
</Tip>

<Tip>
  **Download Links**: Use `invoiceUrl` to allow users to download/view invoice PDFs.
</Tip>

<Tip>
  **Date Formatting**: Format `createdAt` and `paidAt` for user's locale.
</Tip>

<Tip>
  **Status Badges**: Show visual indicators (colors/icons) for different invoice statuses.
</Tip>

<Warning>
  **10 Invoice Limit**: Endpoint returns max 10 invoices. For full history, direct users to Dodo Payments billing portal.
</Warning>

<Warning>
  **Amount in Cents**: `amount` field is in cents. Always divide by 100 before displaying to users.
</Warning>

<Warning>
  **Invoice URLs**: Invoice URLs may be temporary. Don't cache them - fetch fresh on each page load.
</Warning>

## Integration Examples

### Invoice History Table

```javascript theme={null}
function InvoiceHistoryTable() {
  const [invoices, setInvoices] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function loadInvoices() {
      try {
        const response = await fetch('/api/billing/invoices', {
          headers: { 'Authorization': `Bearer ${apiKey}` }
        });

        const { invoices } = await response.json();
        setInvoices(invoices);
      } finally {
        setLoading(false);
      }
    }

    loadInvoices();
  }, []);

  if (loading) return <div>Loading invoices...</div>;

  if (invoices.length === 0) {
    return <div>No invoices yet</div>;
  }

  return (
    <table className="invoice-table">
      <thead>
        <tr>
          <th>Invoice #</th>
          <th>Date</th>
          <th>Amount</th>
          <th>Status</th>
          <th>Download</th>
        </tr>
      </thead>
      <tbody>
        {invoices.map(invoice => (
          <tr key={invoice.id}>
            <td>{invoice.invoiceNumber}</td>
            <td>{new Date(invoice.createdAt).toLocaleDateString()}</td>
            <td>€{(invoice.amount / 100).toFixed(2)}</td>
            <td>
              <StatusBadge status={invoice.status} />
            </td>
            <td>
              <a href={invoice.invoiceUrl} target="_blank" rel="noopener noreferrer">
                Download PDF
              </a>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
```

### Invoice Status Badge

```javascript theme={null}
function StatusBadge({ status }) {
  const statusConfig = {
    paid: { color: 'green', text: 'Paid', icon: '✓' },
    open: { color: 'yellow', text: 'Pending', icon: '⏳' },
    void: { color: 'gray', text: 'Void', icon: '✗' },
    uncollectible: { color: 'red', text: 'Failed', icon: '!' },
  };

  const config = statusConfig[status] || statusConfig.open;

  return (
    <span className={`badge badge-${config.color}`}>
      {config.icon} {config.text}
    </span>
  );
}
```

### Invoice Summary Card

```javascript theme={null}
function InvoiceSummaryCard() {
  const [summary, setSummary] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function loadSummary() {
      const response = await fetch('/api/billing/invoices', {
        headers: { 'Authorization': `Bearer ${apiKey}` }
      });

      const { invoices } = await response.json();

      const paidInvoices = invoices.filter(inv => inv.status === 'paid');
      const totalSpent = paidInvoices.reduce((sum, inv) => sum + inv.amount, 0) / 100;

      setSummary({
        totalInvoices: invoices.length,
        totalPaid: paidInvoices.length,
        totalSpent,
        lastPayment: paidInvoices[0] || null
      });

      setLoading(false);
    }

    loadSummary();
  }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <div className="summary-card">
      <h3>Billing Summary</h3>

      <div className="stats">
        <div className="stat">
          <label>Total Invoices</label>
          <value>{summary.totalInvoices}</value>
        </div>

        <div className="stat">
          <label>Total Spent</label>
          <value>€{summary.totalSpent.toFixed(2)}</value>
        </div>

        {summary.lastPayment && (
          <div className="stat">
            <label>Last Payment</label>
            <value>
              €{(summary.lastPayment.amount / 100).toFixed(2)} on{' '}
              {new Date(summary.lastPayment.paidAt).toLocaleDateString()}
            </value>
          </div>
        )}
      </div>
    </div>
  );
}
```

### Download All Invoices

```javascript theme={null}
async function downloadAllInvoices() {
  const response = await fetch('/api/billing/invoices', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });

  const { invoices } = await response.json();

  // Open each invoice URL in new tab
  invoices.forEach((invoice, index) => {
    setTimeout(() => {
      window.open(invoice.invoiceUrl, '_blank');
    }, index * 500); // Stagger to avoid popup blocker
  });

  toast.success(`Opening ${invoices.length} invoice(s) in new tabs`);
}
```

## Related Endpoints

* [Get Subscription](/api-reference/billing/get-subscription) - GET current subscription status
* [Create Checkout Session](/api-reference/billing/create-checkout-session) - POST to start subscription
* [Create Portal Session](/api-reference/billing/create-portal-session) - POST to manage subscription
* [Get Usage](/api-reference/billing/get-usage) - GET current usage metrics
