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

# Export costs as FOCUS 1.2 rows

> Returns the account's costs as [FOCUS 1.2](https://focus.finops.org) rows, one per resource, meter and day, plus one row per plan fee, add-on, tax, discount and credit.

Rows for a finalized invoice add up to that invoice. The billing cycle that has not been invoiced yet is estimated: those rows carry `x_Estimated: "true"` and the response has `complete: false`. Request the same window again after the invoice is finalized to get the final rows.

A row belongs to the window that contains its `ChargePeriodStart`, so consecutive windows never repeat or drop a row.

An API key reads the account it was issued for. A signed-in user reads their own account, or a team with `teamId`.

**API key scope:** `billing.read`

**Team role permission:** `billing.manage`



## OpenAPI

````yaml api-reference/core.openapi.yaml GET /v1/billing/focus
openapi: 3.0.3
info:
  title: Brimble API
  version: 1.0.0
  description: >
    The Brimble API lets you deploy and manage projects, databases, domains,
    sandboxes, object storage and more.


    ## Base URL


    All endpoints are relative to `https://api.brimble.io/core`, for example
    `GET https://api.brimble.io/core/v1/projects`.


    ## Authentication


    Create an API key in the dashboard under **Settings → API keys** and send it
    in the `x-brimble-key` header:


    ```

    x-brimble-key: <your API key>

    ```


    Each API key carries permission scopes such as `project.read` or
    `project.deploy`. Every endpoint lists the scope it needs; a key without
    that scope gets `403`. Dashboard session tokens (`Authorization: Bearer
    <token>`) are also accepted, but integrations should use API keys.


    ## Teams


    Endpoints act on your personal workspace unless you pass a team. Most
    endpoints accept `teamId` (as a query parameter, or in the body for writes).
    API keys created for a team act in that team. Inside a team, your team role
    must also allow the action; each endpoint lists the team permission it
    checks.


    ## Responses


    Successful responses are JSON with this shape:


    ```json

    { "message": "Projects fetched", "data": { } }

    ```


    Errors return a `message`:


    ```json

    { "message": "Project not found", "data": {} }

    ```


    Requests that fail validation return `400` with every invalid field:


    ```json

    { "errors": [{ "type": "field", "msg": "Project name should be provided",
    "path": "name", "location": "body" }] }

    ```


    ## Rate limits


    Requests made with an API key are rate limited. Responses include
    `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` and
    `X-RateLimit-Bucket`. Command execution and file transfer endpoints use
    separate buckets.


    ## Idempotency


    Endpoints that accept an `Idempotency-Key` header return the original result
    when retried with the same key and body, instead of repeating the operation.


    ## Streaming


    Command execution endpoints can stream output as Server-Sent Events
    (`text/event-stream`). Each event is `data: <json>` where the JSON has a
    `type` of `stdout`, `stderr`, `done` or `error`.


    ## Webhooks


    To receive events instead of polling, configure a webhook with `PATCH
    /v1/webhooks`. See the [Webhooks guide](/webhooks/overview) and the [Webhook
    events reference](/webhooks/events) for every payload.
  contact:
    name: Brimble
    url: https://brimble.io
servers:
  - url: https://api.brimble.io/core
    description: Production
security:
  - ApiKeyAuth: []
  - BearerAuth: []
tags:
  - name: Projects
    description: Create, deploy, configure and manage projects.
  - name: Deployments and Logs
    description: Deployment history, build logs and request logs.
  - name: Environments
    description: Project environments (production, staging, previews) and their variables.
  - name: Secrets
    description: >-
      Secrets (environment variables) set on a single project. Not to be
      confused with Environments, which group projects into production, staging
      and preview. Secret values are encrypted at rest and returned encrypted;
      use `POST /v1/decrypt` to read them.
  - name: Webhooks
    description: >-
      Receive events from Brimble at your own endpoint (or a Discord or Slack
      channel). Configure the destination and events with `PATCH /v1/webhooks`;
      use `*` to receive every event.


      See the [Webhooks guide](/webhooks/overview) for setup, and the [Webhook
      events reference](/webhooks/events) for the payload each event delivers.


      | Event | Sent when |

      | --- | --- |

      | `project.created` | A project is created |

      | `project.updated` | A project is updated |

      | `project.deleted` | A project is deleted |

      | `project.domain.updated` | A project domain changes |

      | `deployment.created` | A deployment is queued |

      | `deployment.started` | A deployment starts |

      | `deployment.success` | A deployment succeeds |

      | `deployment.failed` | A deployment fails |

      | `environment.variables.added` | Environment variables are added |

      | `environment.variables.updated` | Environment variables are updated |

      | `environment.variables.deleted` | Environment variables are deleted |

      | `domain.created` | A domain is added |

      | `domain.purchased` | A domain is purchased |

      | `domain.renewed` | A domain is renewed |

      | `domain.expired` | A domain expires |

      | `dns.record.created` | A DNS record is created |

      | `dns.record.updated` | A DNS record is updated |

      | `dns.record.deleted` | A DNS record is deleted |

      | `database.created` | A database is created |

      | `database.backup.completed` | A database backup completes |

      | `autoscaling.group.created` | An autoscaling rule is created |

      | `autoscaling.group.updated` | An autoscaling rule is updated |

      | `autoscaling.group.deleted` | An autoscaling rule is deleted |

      | `payment.successful` | A payment succeeds |

      | `payment.failed` | A payment fails |


      Test deliveries sent with `POST /v1/webhooks/test` include the header
      `X-Brimble-Test: true`.
  - name: Git Providers
    description: Connected git accounts, repositories and linking repositories to projects.
  - name: Domains
    description: Custom domains, DNS records and domain registration.
  - name: Databases
    description: 'Managed databases: provisioning, backups, users and linking to projects.'
  - name: Log Drains
    description: Stream logs to external destinations.
  - name: Sandboxes
    description: Isolated sandboxes for running code, with files and snapshots.
  - name: CI Runners
    description: Run GitHub Actions jobs for an organization on Brimble sandboxes.
  - name: Object Storage
    description: S3-compatible buckets, objects and credentials.
  - name: Scaling and Networking
    description: Autoscaling rules, networking and CDN cache, and rate limits.
  - name: Teams
    description: Teams, members, invitations and roles.
  - name: Tags
    description: Label projects with tags and filter by them.
  - name: Billing
    description: Costs per resource in FOCUS 1.2 format, for cost tools such as CostGraph.
  - name: Catalog
    description: Regions, frameworks and plans. No authentication required.
paths:
  /v1/billing/focus:
    get:
      tags:
        - Billing
      summary: Export costs as FOCUS 1.2 rows
      description: >-
        Returns the account's costs as [FOCUS 1.2](https://focus.finops.org)
        rows, one per resource, meter and day, plus one row per plan fee,
        add-on, tax, discount and credit.


        Rows for a finalized invoice add up to that invoice. The billing cycle
        that has not been invoiced yet is estimated: those rows carry
        `x_Estimated: "true"` and the response has `complete: false`. Request
        the same window again after the invoice is finalized to get the final
        rows.


        A row belongs to the window that contains its `ChargePeriodStart`, so
        consecutive windows never repeat or drop a row.


        An API key reads the account it was issued for. A signed-in user reads
        their own account, or a team with `teamId`.


        **API key scope:** `billing.read`


        **Team role permission:** `billing.manage`
      operationId: getFocusBilling
      parameters:
        - name: charge_period_start
          in: query
          required: false
          description: Start of the window, ISO 8601. Required unless `invoice_id` is sent.
          schema:
            type: string
            format: date-time
        - name: charge_period_end
          in: query
          required: false
          description: >-
            End of the window, exclusive. At most 366 days after the start.
            Required unless `invoice_id` is sent.
          schema:
            type: string
            format: date-time
        - name: invoice_id
          in: query
          required: false
          description: Export a single finalized invoice instead of a window.
          schema:
            type: string
        - name: teamId
          in: query
          required: false
          description: >-
            Team to read. Ignored for a team API key, which always reads its own
            team.
          schema:
            type: string
      responses:
        '200':
          description: FOCUS rows for the window.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      focus_version:
                        type: string
                        example: '1.2'
                      charge_period_start:
                        type: string
                        format: date-time
                      charge_period_end:
                        type: string
                        format: date-time
                      complete:
                        type: boolean
                        description: >-
                          False when any row is estimated or part of the usage
                          could not be read.
                      rows:
                        type: array
                        items:
                          type: object
                          description: >-
                            One FOCUS 1.2 record. Costs and quantities are
                            decimal strings.
                          additionalProperties: true
                          example:
                            BillingAccountId: cus_123
                            BillingCurrency: USD
                            BillingPeriodStart: '2026-10-05T09:52:00+00:00'
                            BillingPeriodEnd: '2026-11-05T09:52:00+00:00'
                            ChargePeriodStart: '2026-10-06T00:00:00+00:00'
                            ChargePeriodEnd: '2026-10-07T00:00:00+00:00'
                            ChargeCategory: Usage
                            ChargeDescription: CPU · api
                            Provider: brimble
                            ServiceName: Compute
                            ServiceCategory: Compute
                            ResourceId: 6a4a4fce5fed1a67d9108e73
                            ResourceName: api
                            ResourceType: Project
                            RegionId: eu-central
                            BilledCost: '0.033462'
                            EffectiveCost: '0.033462'
                            ListCost: '0.033300'
                            ConsumedQuantity: '0.0333'
                            ConsumedUnit: vCPU-months
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/ServerError'
components:
  responses:
    ValidationError:
      description: Request validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationErrorResponse'
    Unauthorized:
      description: Missing, invalid or expired credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: >-
        The API key lacks the required scope, your team role lacks the
        permission, or the feature is not available on your account
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServerError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ValidationErrorResponse:
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          description: One entry per invalid field.
          items:
            type: object
            properties:
              type:
                type: string
                description: Always `field`.
                example: field
              value:
                description: Value that was sent.
              msg:
                type: string
                description: What is wrong with the value.
                example: Invalid value
              path:
                type: string
                description: >-
                  Name of the invalid field. Nested fields use dots, for example
                  `repo.branch`.
                example: name
              location:
                type: string
                description: Part of the request the field was in.
                enum:
                  - body
                  - query
                  - params
                  - headers
                  - cookies
    ErrorResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Human-readable error message.
          example: Project not found
        data:
          type: object
          description: Always empty on errors.
          example: {}
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-brimble-key
      description: >-
        API key created in the dashboard under Settings → API keys. Each key
        carries permission scopes; every endpoint lists the scope it needs.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Dashboard session token. Use an API key for integrations.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.