# Public API data formats

The [OpenAPI document](/openapi/public.v1.json) declares each field's format. This page explains the ones an integration has to handle with care.

## Money

Every amount of money is a decimal string, never a JSON number, so no client sums binary floats that drift:

```json
{ "amount": "1250.50000000", "currency": "EUR" }
```

- Responses write every amount with exactly eight decimals, a point and no exponent.
- Requests send an amount the same way, with up to eight decimals: `"1250.5"` and `"1250.50000000"` are the same amount. A JSON number, an exponent or a thousands separator is refused with `400`.
- A budget amount is kept to the cent, so a budget amount with more than two decimals is refused rather than rounded.
- Compare amounts by value, not as text: `"49"` and `"49.00000000"` are equal.
- Percentages, ratios such as allocation coverage, exchange rates and usage quantities stay JSON numbers.
- A cost alert's `thresholdValue` is a decimal string whether it is an amount or a percentage, as its `thresholdType` says.

## Dates and months

- A date is `YYYY-MM-DD`, such as `startDate`, `endDate` and a custom integration's `chargePeriodStart`. A charge period is a day, so a time is refused.
- A forecast month is `YYYY-MM`.
- A timestamp, such as `createdAt`, is an ISO 8601 date and time.

## Currencies

A currency is an upper-case three-letter ISO 4217 code, such as `EUR` or `GBP`.

## IDs

Every Costfluent object is addressed by a prefixed ID, such as `wsp_` for a workspace, `bud_` for a budget, `crp_` for a cost report, `seg_` for a segment and `prv_` for an integration. The prefix says what the ID names, and the API refuses an ID of the wrong kind. Treat the rest as opaque.

A batch of costs sent to a custom integration answers with a `batchId` beginning with `cbt_`: a receipt for that batch, not an upload you can read back.

## Conditional updates

A budget read answers with an `ETag` header, the version of the budget it returned. Send it back as `If-Match` on the `PUT` that changes the budget:

```bash
curl --request PUT https://api.costfluent.com/v1/budgets/$BUDGET_ID \
  --header "Authorization: Bearer $COSTFLUENT_API_TOKEN" \
  --header "If-Match: \"774\"" \
  --header "Content-Type: application/json" \
  --data '{"amount": "15000"}'
```

When someone changed the budget after your read, the `PUT` is refused with `412` and `precondition_failed`, and nothing changes: read it again, then decide. Without `If-Match`, the last write wins.

## How it behaves

- The create and the update of a budget answer with its new `ETag` too.
- `If-Match: *` applies the update whatever the version.
- The Terraform provider sends the `ETag` of its last read, so an edit made in Costfluent between a plan and its apply stops the apply instead of being overwritten.

## Related

- [Errors](/api/errors)
- [Public API versioning](/api/versioning)
- [API reference](/api)
