# Bills

Billing and wallet management. Requires a **non-free** company plan. Pilots need `billing: true` on their user record to appear in billing operations.

***

## List Bills (Pilot Wallet)

<mark style="color:blue;">`GET`</mark> `/bills/index.json`

<mark style="color:blue;">`GET`</mark> `/bills/index/{userId}.json`

<mark style="color:blue;">`GET`</mark> `/bills/index/{userId}/{offset}.json`

List wallet movement records for a pilot. Managers can view any pilot's bills; regular users (`user_group_id ≥ 150`) see only their own. Linked flight info is included if the flight is not deleted.

#### Query Parameters

| Parameter | Type   | Description                    |
| --------- | ------ | ------------------------------ |
| limit     | number | Records per page (default: 10) |

#### Response

```json
{
  "bills": [
    {
      "UserBill": {
        "id": "xyz789",
        "user_id": "100",
        "company_id": "42",
        "flight_id": "5678",
        "name": "2025-01-10 LEBL-LEMD",
        "price": "-120.00",
        "total": "-120.00",
        "receipt": false,
        "created": "2025-01-10 15:00:00"
      },
      "Flight": {
        "callsign": "EC-ABC",
        "rules": "IFR",
        "offblocks_time": "1736505000",
        "block_time": "6900",
        "deleted": false
      }
    }
  ],
  "total": 42
}
```

***

## View Bill

<mark style="color:blue;">`GET`</mark> `/bills/view/{id}.json`

Full detail for a single bill including client info, company billing settings, and linked flight. Access does not require authentication (allowed in `beforeFilter`).

#### Path Parameters

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| id        | UUID | Bill ID     |

#### Response

```json
{
  "bill": {
    "UserBill": {
      "id": "xyz789",
      "n_id": 12,
      "name": "2025-01-10 LEBL-LEMD",
      "price": -120.00,
      "price_hour": -60.00,
      "airport": 0.0,
      "fuel": 0.0,
      "handling": 0.0,
      "others": 0.0,
      "collected_tax": 0.0,
      "subtotal": -120.00,
      "total": -120.00,
      "packaged": 0.0,
      "packaged_time": 0.0,
      "billed_time": 2.0,
      "balance": -120.00,
      "receipt": false
    },
    "Flight": {
      "date": "2025-01-10",
      "callsign": "EC-ABC",
      "departure_airport": "LEBL",
      "landing_airport": "LEMD",
      "flight_time": "6900",
      "block_time": "6900",
      "rules": "IFR",
      "landings": 1
    },
    "Client": {
      "id": "100",
      "UserDetail": { "name": "John", "surname": "Doe", "passport": "AB123456", "phone": "+34600000000", "address": "...", "city": "Barcelona", "pc": "08001", "Country": { "name": "Spain" } },
      "Company": {
        "name": "My FTO",
        "CompanyDetail": { "Country": { "name": "Spain" } },
        "CompanyBillingSetting": { "tax": "21", "billed_person": "pilot", "send_notification": true }
      }
    },
    "Creator": {
      "id": "50",
      "UserDetail": { "name": "Admin", "surname": "User" }
    },
    "UserBillPackageFlight": []
  }
}
```

***

## Create Manual Bill

<mark style="color:green;">`POST`</mark> `/bills/create.json`

Create a manual wallet transaction for one or more pilots. If `id` is provided, updates an existing record. `user_id` can be a single UUID, an array of UUIDs, or a pilot group UUID (group members are expanded automatically). Restricted to `user_group_id ≤ 145`.

#### Request Body

| Field    | Type            | Required  | Description                                   |
| -------- | --------------- | --------- | --------------------------------------------- |
| user\_id | string \| array | Yes (new) | Pilot UUID(s) or pilot group UUID             |
| price    | number          | Yes (new) | Amount (negative = charge, positive = credit) |
| name     | string          | Yes       | Transaction description                       |
| created  | string          | No        | Transaction date (defaults to now)            |
| receipt  | boolean         | No        | Mark as a receipt                             |
| id       | UUID            | No        | Existing bill ID to update                    |

#### Response

```json
{
  "result": true,
  "new": true,
  "UserBills": [
    {
      "id": "xyz789",
      "user_id": "100",
      "name": "Manual adjustment",
      "price": "-50.00",
      "creator": "Admin User",
      "client": "John Doe"
    }
  ],
  "errors": []
}
```

***

## Bill a Flight

<mark style="color:blue;">`GET`</mark> `/bills/flight.json?id={flightId}`

<mark style="color:green;">`POST`</mark> `/bills/flight.json?id={flightId}`

Retrieve flight billing data (GET) or create/update a flight bill (POST). Flight must be confirmed and not deleted.

#### Query Parameters

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| id        | UUID | Flight ID   |

#### Request Body (POST)

| Field         | Type    | Required | Description                            |
| ------------- | ------- | -------- | -------------------------------------- |
| user\_id      | UUID    | Yes      | Pilot to bill                          |
| price\_hour   | number  | Yes      | Hourly rate                            |
| price         | number  | Yes      | Total flight price                     |
| airport       | number  | No       | Airport fees                           |
| fuel          | number  | No       | Fuel charges                           |
| handling      | number  | No       | Handling charges                       |
| others        | number  | No       | Other charges                          |
| rate\_id      | UUID    | No       | Rate record to use                     |
| notify        | boolean | No       | Send notification email to pilot       |
| use\_packages | boolean | No       | Deduct from pilot's package balance    |
| created       | string  | No       | Bill date (defaults to onblocks\_time) |

#### Response

```json
{
  "defaults": { "tax": "21", "default_airport": "0", ... },
  "payment": { "UserBill": { ... } },
  "flight": { "Flight": { ... }, "Aircraft": { ... }, "UserBill": { ... } },
  "errors": null
}
```

***

## Delete Bill

<mark style="color:green;">`POST`</mark> `/bills/delete.json`

Delete a bill and recalculate the pilot's balance.

#### Request Body

| Field | Type | Required | Description       |
| ----- | ---- | -------- | ----------------- |
| bill  | UUID | Yes      | Bill ID to delete |

#### Response

```json
{
  "result": true,
  "balance": -240.00,
  "bill": { "UserBill": { "id": "xyz789", "name": "...", "total": "-120.00" } }
}
```

***

## Auto-Bill a Flight

<mark style="color:blue;">`GET`</mark> `/bills/autobill/{flightId}.json`

<mark style="color:blue;">`GET`</mark> `/bills/autobill/{flightId}/{userId}.json`

<mark style="color:green;">`POST`</mark> `/bills/autobill.json`

Automatically generate a bill for a flight using the aircraft's default rate. Any existing bill for the flight is replaced. Optionally override which pilot to bill.

#### Request Body (POST)

| Field  | Type | Required | Description            |
| ------ | ---- | -------- | ---------------------- |
| flight | UUID | Yes      | Flight ID              |
| user   | UUID | No       | Override pilot to bill |

#### Response

```json
{
  "bill": { "UserBill": { ... } }
}
```

***

## Get Pilot Balance

<mark style="color:blue;">`GET`</mark> `/bills/balance.json`

<mark style="color:blue;">`GET`</mark> `/bills/balance/{userId}.json`

Returns the current wallet balance for a pilot. Managers can query any billable pilot. Regular users see only their own balance.

#### Response

```json
{
  "balance": -240.50
}
```

***

## Create Stripe Payment Intent

<mark style="color:blue;">`GET`</mark> `/bills/pay.json`

<mark style="color:green;">`POST`</mark> `/bills/pay.json`

Initiate a Stripe Checkout session to allow a pilot to pay their balance. Requires Stripe to be enabled and configured for the company.

#### Request Body (POST)

| Field  | Type   | Required | Description                                 |
| ------ | ------ | -------- | ------------------------------------------- |
| amount | number | No       | Amount to pay (defaults to current balance) |

#### Response

```json
{
  "result": true,
  "message": "Payment intent created, redirecting to Stripe checkout.",
  "redirect_url": "https://checkout.stripe.com/..."
}
```

***

## Complete Stripe Checkout

<mark style="color:blue;">`GET`</mark> `/bills/checkout/{token}.json`

Process a completed Stripe Checkout session. Called automatically via the Stripe `success_url` redirect. Verifies payment status, records the credit, and notifies company managers.

#### Path Parameters

| Parameter | Type   | Description                |
| --------- | ------ | -------------------------- |
| token     | string | Stripe Checkout session ID |

#### Response

```json
{
  "result": true,
  "message": "Payment received, thank you!"
}
```

***

## Download Bills (XLS)

<mark style="color:blue;">`GET`</mark> `/bills/download.json`

<mark style="color:blue;">`GET`</mark> `/bills/download/{userId}.json`

Download all bills as an Excel file. Regular users see only their own. Requires token query param.

***

## List Rates

<mark style="color:blue;">`GET`</mark> `/bills/rates.json`

<mark style="color:blue;">`GET`</mark> `/bills/rates/true.json`

List all billing rates for the company. Pass `true` to return only package rates.

#### Response

```json
{
  "rates": [
    {
      "Rate": {
        "id": "r1",
        "company_id": "42",
        "name": "C172 Standard",
        "hourly_price": "120.00",
        "pack": false,
        "deleted": false
      },
      "Aircraft": [
        { "id": "45", "registration": "EC-ABC" }
      ]
    }
  ]
}
```

***

## View Rate

<mark style="color:blue;">`GET`</mark> `/bills/rate/{id}.json`

Retrieve a single rate with linked aircraft.

***

## Get Rates for Aircraft

<mark style="color:blue;">`GET`</mark> `/bills/aircraft/{aircraftId}.json`

List all rates configured for a specific aircraft.

***

## List Packages (Pilot)

<mark style="color:blue;">`GET`</mark> `/bills/packages/{userId}.json`

<mark style="color:blue;">`GET`</mark> `/bills/packages/{userId}/true.json`

List flight-hour packages for a pilot. Pass `true` to return only valid packages (non-expired with remaining balance).

#### Response

```json
{
  "packages": [
    {
      "UserBillPackage": {
        "id": "pkg1",
        "user_id": "100",
        "total": "50.00",
        "balance": "32.50",
        "expiration": "2026-12-31",
        "created": "2025-01-01 10:00:00"
      },
      "Rate": [{ "id": "r1", "name": "C172 Standard", "hourly_price": "120.00" }]
    }
  ]
}
```

***

## View Package

<mark style="color:blue;">`GET`</mark> `/bills/package/{id}.json`

Full details for a package including the pilot, creator, linked rate, bills, and associated flights.

***

## Create / Update Package

<mark style="color:green;">`POST`</mark> `/bills/manager_purchase_package.json`

Create or update a flight-hour package for a pilot. Optionally creates a debit bill for the package cost.

#### Request Body

| Field      | Type                | Required  | Description                                          |
| ---------- | ------------------- | --------- | ---------------------------------------------------- |
| user\_id   | UUID                | Yes (new) | Pilot to assign the package to                       |
| rate\_id   | array               | Yes       | Array of rate UUIDs to include                       |
| total      | number              | Yes       | Total hours in the package                           |
| id         | UUID                | No        | Existing package ID to update                        |
| expiration | string \| timestamp | No        | Package expiry date                                  |
| bill       | string              | No        | `1` to also create a debit bill for the package cost |

#### Response

```json
{
  "new": true,
  "package": { "UserBillPackage": { "id": "pkg1", "balance": "50.00", ... } },
  "bill": "xyz789",
  "errors": null
}
```

***

## Delete Package

<mark style="color:green;">`POST`</mark> `/bills/manager_delete_package.json`

Delete a package and its associated bill (if any). Recalculates the pilot's balance.

#### Request Body

| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| id    | UUID | Yes      | Package ID  |

***

## Manager: List All Bills

<mark style="color:blue;">`GET`</mark> `/bills/manager_index.json`

<mark style="color:blue;">`GET`</mark> `/bills/manager_index/{type}.json`

Paginated list of all company bills. `type` is `transactions` (default, non-flight bills) or `flights` (flight-linked bills).

#### Named Parameters / POST Filters

| Parameter | Description                                           |
| --------- | ----------------------------------------------------- |
| from      | Start date filter                                     |
| to        | End date filter                                       |
| pilot     | Filter by pilot user ID                               |
| excel     | Append `excel:true` for XLS download (requires token) |

***

## Manager: Bill Stats

<mark style="color:blue;">`GET`</mark> `/bills/manager_stats/{type}.json`

<mark style="color:green;">`POST`</mark> `/bills/manager_stats/{type}.json`

Aggregated stats over the **full** filtered set (not paginated). Same `type` and filters as `manager_index` — `from`, `to`, `pilot`. Filters can be sent as POST body or query string. Designed to be fetched in parallel with the first page of `manager_index` and refetched on every filter change. Charts read from this response, not from the paginated bill list.

`type`: `transactions` (default, `flight_id = ''`) or `flights` (`flight_id <> ''`).

`totalSeconds` is `SUM(billed_time) * 3600` (billed\_time stored as hours). `topClients` returns up to 10 entries ordered by `ABS(SUM(total))` desc.

#### Filters (POST body or query string)

| Parameter | Description                               |
| --------- | ----------------------------------------- |
| from      | Start date (anything `strtotime` accepts) |
| to        | End date (anything `strtotime` accepts)   |
| pilot     | Filter by pilot user ID                   |

#### Response

```json
{
  "stats": {
    "type": "transactions",
    "count": 1842,
    "total": 125430.55,
    "avg": 68.10,
    "positive": 145200.00,
    "negative": -19769.45,
    "totalSeconds": 0,
    "monthly": [
      {
        "month": "2026-01",
        "count": 312,
        "total": 21500.00,
        "positive": 24000.00,
        "negative": -2500.00,
        "totalSeconds": 0
      }
    ],
    "topClients": [
      {
        "user_id": "100",
        "name": "John Doe",
        "count": 87,
        "total": 9420.00,
        "totalSeconds": 0
      }
    ]
  }
}
```

For `type=flights`, `totalSeconds` reflects flight billed time across the filtered set.

***

## Manager: List Billable Pilots

<mark style="color:blue;">`GET`</mark> `/bills/manager_pilots.json`

<mark style="color:blue;">`GET`</mark> `/bills/manager_pilots/{aircraftId}.json`

List all active, non-deleted pilots with `billing: true`. If an aircraft ID is provided, also returns each pilot's configured hourly price for that aircraft.

#### Response

```json
{
  "pilots": [
    { "id": "100", "name": "John Doe", "group": "170", "groupname": "Pilot", "price": "120.00" }
  ]
}
```

***

## Manager: List All Packages

<mark style="color:blue;">`GET`</mark> `/bills/manager_packages.json`

Paginated list of all packages across all company pilots.

***

## Manager: Billable Flights

<mark style="color:blue;">`GET`</mark> `/bills/manager_flights.json`

Paginated list of flights on billing-enabled aircraft. Supports named parameter filters:

| Named Param   | Description                          |
| ------------- | ------------------------------------ |
| pilot         | Filter by PIC or SIC user ID         |
| status        | `billed` or `notbilled`              |
| base          | Filter by base ID                    |
| flight\_type  | Filter by flight type ID             |
| flight\_rules | Filter by rules (`IFR`, `VFR`)       |
| from          | Filter from date                     |
| to            | Filter to date                       |
| excel         | Append `excel:true` for XLS download |

***

## Manager: Create / Update Rate

<mark style="color:green;">`POST`</mark> `/bills/manager_rate_edit.json`

Create or update a billing rate and assign aircraft.

#### Request Body

| Field              | Type    | Required | Description                |
| ------------------ | ------- | -------- | -------------------------- |
| Rate.id            | UUID    | No       | Existing rate ID to update |
| Rate.name          | string  | Yes      | Rate name                  |
| Rate.hourly\_price | number  | Yes      | Price per hour             |
| Rate.pack          | boolean | No       | Is this a package rate     |
| Rate.aircraft\_id  | array   | No       | Aircraft UUIDs to link     |

***

## Manager: Delete Rate

<mark style="color:green;">`POST`</mark> `/bills/manager_rate_delete.json`

Soft-delete a rate and remove all aircraft-rate associations.

#### Request Body

| Field  | Type | Required | Description       |
| ------ | ---- | -------- | ----------------- |
| rateId | UUID | Yes      | Rate ID to delete |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flylogs.com/fcom/api-docs/reference/bills.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
