Skip to content
Merged
2 changes: 2 additions & 0 deletions src/content/docs/customizing-fossbilling/company.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ https://example.com

This signature appears at the bottom of most automated emails. You can still override it in individual templates.

For more control over generated output, see [Email Templates](/customizing-fossbilling/email-templates/) and [Customizing Invoice PDFs](/customizing-fossbilling/invoice-pdf/).

## Currency Settings

Also in **Configuration → Settings → Currency**:
Expand Down
27 changes: 21 additions & 6 deletions src/content/docs/customizing-fossbilling/config.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,36 @@ Temporarily disable public access. Use `allowed_urls` for endpoints that must st

### API Settings

Control API access and rate limiting. Use `require_referrer_header` to lock browser-originated requests to your install URL, `allowed_ips` for explicit allowlists, and the `rate_*` values to tune throttling.
Control API access.

- Use `require_referrer_header` to lock browser-originated requests to your install URL, and `allowed_ips` for explicit allowlists.
- Keep `CSRFPrevention` enabled. The bundled [JavaScript API wrapper](/developing-fossbilling/javascript/) handles CSRF tokens for session-authenticated browser calls.

```php
'api' => [
'require_referrer_header' => true,
'allowed_ips' => [],
'rate_span' => 60,
'rate_limit' => 100,
'throttle_delay' => 2,
'rate_span_login' => 60,
'rate_limit_login' => 20,
'CSRFPrevention' => true,
],
```

### Rate Limiter
FOSSBilling includes a built-in rate limiter which depends on Symfony's [rate limiter](https://symfony.com/doc/current/rate_limiter.html) component.

`policies` is an empty array by default and inherits sensible defaults from [`FOSSBilling\Security\RateLimiter::getDefaultConfig()`](https://github.com/FOSSBilling/FOSSBilling/blob/main/src/library/FOSSBilling/Security/RateLimiter.php#L37).

Any policy you explicitly set in the `policies` array will override the default one. We have included an example below. You can refer to Symfony's documentation on creating rate limiter policies.

```php
'rate_limiter' => [
'enabled' => true,
'whitelist_ips' => [], // Array of whitelisted IP addresses and CIDRs
'policies' => [
'client_signup' => ['policy' => 'fixed_window', 'limit' => 5, 'interval' => '1 hour'],
],
],
```

## Environment Variables

Some settings can be overridden via environment variables:
Expand Down
8 changes: 4 additions & 4 deletions src/content/docs/customizing-fossbilling/email-templates.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ See [Twig Filters & Functions](/developing-fossbilling/twig-filters/) for all av

### Markdown Format

Default templates use Markdown for simple formatting. Wrap your content with the `apply markdown` filter:
Default templates use Markdown for simple formatting. Wrap your content with the `apply markdown_to_html` filter:

```twig
\{% apply markdown %\}
\{% apply markdown_to_html %\}
Hi \{\{ staff.name \}\},

If you are reading this email, FOSSBilling is **configured properly** and is **able to send emails**.
Expand Down Expand Up @@ -108,7 +108,7 @@ For full control, use HTML:

Templates exist in two places:

1. **Module source** — `modules/{Module}/html_email/`
1. **Module source** — `modules/{Module}/templates/email/`
2. **Database** — `email_template` table (copied there when module is installed)

After installation, edit templates through the admin panel or directly in the database. Changes made only to the module files will not apply until you regenerate the templates.
Expand All @@ -121,4 +121,4 @@ After installation, edit templates through the admin panel or directly in the da

## Example Module

See the [example module](https://github.com/FOSSBilling/example-module/tree/main/html_email) for more template examples.
See the [core email templates](https://github.com/FOSSBilling/FOSSBilling/tree/main/src/modules/Email/templates/email) for more template examples.
69 changes: 41 additions & 28 deletions src/content/docs/customizing-fossbilling/invoice-pdf.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ FOSSBilling generates invoice PDFs with [Dompdf](https://github.com/dompdf/dompd

## CSS Limitations

Dompdf doesn't support everything. As of version 2.0.3:
Dompdf is not a complete PDF engine. FOSSBilling uses Dompdf 3.x, which supports many print-friendly CSS features but still has layout limitations:

| Supported | Not Supported |
|-----------|---------------|
| CSS 2.1 and some CSS3 | Flexbox |
| `@import`, `@media`, `@page` | CSS Grid |
| Basic positioning | Complex layouts |
| CSS custom properties and math functions such as `calc()` | Browser-style complex layouts |
| Basic positioning and table layouts | Splitting table rows or cells across pages |

{% aside type="tip" %}
Table cells can't span pages. Keep table rows compact enough to fit on one page.
Expand All @@ -23,55 +24,66 @@ Table cells can't span pages. Keep table rows compact enough to fit on one page.

### Creating a Custom Stylesheet

1. Copy `/modules/Invoice/pdf_template/default-pdf.css`
2. Paste as `/modules/Invoice/pdf_template/custom-pdf.css`
1. Copy `/modules/Invoice/templates/pdf/default-invoice.css`
2. Paste as `/modules/Invoice/templates/pdf/custom-invoice.css`

FOSSBilling automatically uses `custom-pdf.css` if it exists.
FOSSBilling automatically uses `custom-invoice.css` if it exists.

{% aside type="caution" %}
Editing `default-pdf.css` directly is overwritten on updates. Always use `custom-pdf.css`.
Editing `default-invoice.css` directly is overwritten on updates. Always use `custom-invoice.css`.
{% /aside %}

### CSS Classes Reference

![PDF layout with CSS classes](../../../assets/invoice-layout.png)

Common classes include:
The default stylesheet uses these classes:

- `.invoice-header` — Company and client info
- `.invoice-details` — Invoice number, date, due date
- `.invoice-items` — Line items table
- `.invoice-totals` — Subtotal, tax, total
- `.invoice-footer` — Terms, notes
- `.CompanyLogo` — Company logo image
- `.TopSectionDivider` — Divider below the header area
- `.InvoiceInfo` — Invoice number, dates, and status
- `.CompanyInfo` — Seller/company heading and details
- `.ClientInfo` — Client heading and details
- `.Breakdown` — Line items, tax, discount, and total table
- `.InvoiceText` — Custom invoice text blocks
- `.InvoiceFooter` — Payment details, company footer, and signature
- `.muted-text` — Muted footer signature text

## Custom HTML Template

**FOSSBilling 0.6.0+**: Customize the HTML structure.
Customize the HTML structure by adding a custom Twig template.

### Creating a Custom Template

1. Copy `/modules/Invoice/pdf_template/default-pdf.twig`
2. Paste as `/modules/Invoice/pdf_template/custom-pdf.twig`
1. Copy `/modules/Invoice/templates/pdf/default-invoice.twig`
2. Paste as `/modules/Invoice/templates/pdf/custom-invoice.twig`

FOSSBilling uses `custom-pdf.twig` automatically.
FOSSBilling uses `custom-invoice.twig` automatically.

### Template Variables

Available in PDF templates:

| Variable | Description |
|----------|-------------|
| `invoice` | Invoice data (id, total, items, etc.) |
| `client` | Client information |
| `company` | Your company details |
| `currency` | Currency code and symbol |
| `currency_code` | Invoice currency code for `format_currency`. |
| `css` | Contents of `custom-invoice.css` or `default-invoice.css`, inserted into the template's `<style>` block. |
| `logo_source` | Resolved company logo source. This can be a local path, a remote URL, an SVG data URI, or an empty string. |
| `seller` | Display-ready seller/company lines keyed by labels such as `Name`, `Address 1`, `Phone`, and `VAT Number`. |
| `seller_lines` | Number of seller lines used by the default template for layout calculations. |
| `footer` | Company footer details, including company name, bank details, address fields, email, phone, VAT/company number, website, and signature. |
| `buyer` | Display-ready buyer/client lines keyed by labels such as `Company`, `Name`, `Address`, `City`, `Country`, `Phone`, and `VAT Number`. |
| `buyer_lines` | Number of buyer lines used by the default template for layout calculations. |
| `invoice` | Full invoice API array. Line items are in `invoice.lines`; raw buyer, seller, and client data are in `invoice.buyer`, `invoice.seller`, and `invoice.client`. |

The PDF renderer does not provide top-level `client`, `company`, or `currency` variables. Use `invoice.client`, `seller`/`footer`, and `currency_code` instead.

### Example: Add a Custom Header

```twig
<div class="custom-header">
<img src="{{ company.logo_url }}" alt="{{ company.name }}">
<h1>INVOICE #{{ invoice.serie_nr }}</h1>
<h1>{{ 'Invoice'|trans }} #{{ invoice.serie_nr }}</h1>
</div>
```

Expand All @@ -80,29 +92,30 @@ Available in PDF templates:
PDF templates support the same [Twig filters](/developing-fossbilling/twig-filters/) available elsewhere in FOSSBilling:

```twig
{{ invoice.total | money }} {# Format as currency #}
{{ invoice.created_at | timeago }} {# Show relative time #}
{{ invoice.total|format_currency(currency_code) }} {# Format as currency #}
{{ invoice.created_at|format_date }} {# Format the invoice date #}
{{ invoice.text_1|default('')|markdown_to_html }} {# Render invoice text as HTML #}
```

## Testing Changes

1. Make your edits to `custom-pdf.css` or `custom-pdf.twig`
1. Make your edits to `custom-invoice.css` or `custom-invoice.twig`
2. Generate a test invoice
3. Download the PDF
4. Review the output

{% aside type="tip" %}
PDF generation is cached. Clear the cache (**System → Tools → Clear cache**) after template changes.
Twig templates may be cached. Clear the cache (**System → Tools → Clear cache**) if template changes do not appear.
{% /aside %}

## Debugging

For complex issues, enable Dompdf debugging in `config.php`:
For complex issues, enable FOSSBilling debug mode in `config.php`:

```php
'dompdf' => [
'debug_and_monitoring' => [
'debug' => true,
],
```

Then review your PHP error logs for Dompdf-related messages.
Then review your PHP or FOSSBilling logs for Dompdf-related messages.
44 changes: 41 additions & 3 deletions src/content/docs/developing-fossbilling/api.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Complete reference for the FOSSBilling REST API.
---

{% aside type="note" %}
Building a theme or module? Use the [JavaScript wrapper](/developing-fossbilling/javascript/) instead of raw API calls when possible. It handles common boilerplate and tracks platform changes more gracefully.
Building a theme or module? Use the [JavaScript wrapper](/developing-fossbilling/javascript/) and Twig API helpers instead of raw browser calls when possible. They handle CSRF tokens and common response behavior for you.
{% /aside %}

## Overview
Expand All @@ -27,8 +27,8 @@ Three main entrypoints:

## Request Format

- **Method:** All requests use POST
- **Format:** JSON for both request and response
- **Method:** Core API routes accept GET and POST. Use POST for requests with a JSON body or form data.
- **Format:** JSON responses. POST requests may send JSON or form data.
- **Naming:** Lowercase with underscores (`change_password`)
- **Nulls:** Blank fields are included as `null`, not omitted
- **Dates:** [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format
Expand All @@ -46,6 +46,44 @@ Authorization: Basic base64_encode('admin:YOUR_API_KEY')

Most HTTP clients (curl, Postman) handle the encoding automatically.

Browser requests from an active client or admin session use the session cookie instead. Those requests must include a valid CSRF token.

## CSRF Tokens

CSRF protection applies to session-authenticated `client` and `admin` browser API calls. It does not apply to `guest` calls or external API calls authenticated with API tokens.

For browser calls, FOSSBilling accepts the token in any of these places:

- `CSRFToken` in the JSON body
- `CSRFToken` in form data or query parameters
- `X-CSRF-Token` request header

The token must match the `csrf_token` cookie or the session token. The bundled [JavaScript API wrapper](/developing-fossbilling/javascript/) reads the cookie and adds the token automatically.

Use Twig helpers for theme and module templates. This way, you don't need to manually attach CSRF tokens to the requests:

```twig
<form action="{{ 'profile/update'|api_url }}" {{ fb_api_form({ message: 'Saved'|trans }) }}>
<input type="text" name="first_name">
<button type="submit">{{ 'Save'|trans }}</button>
</form>
```

For raw `fetch()` requests, send the token yourself:

```javascript
const token = document.cookie.match(/csrf_token=([^;]*)/)?.[1] || '';

fetch('/api/client/profile/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': decodeURIComponent(token),
},
body: JSON.stringify({ first_name: 'Jane' }),
});
```

## Example Requests

{% tabs %}
Expand Down
Loading
Loading