# Costs Cost items, cost changes and provider price changes. **Common tasks** - [Record a cost](#post-organizations-organization-cost-items) **Only in the app:** Nothing. Cost items can be managed with a token. **How it works in the app:** [help article](https://infranest.io/docs/itemised-costs). **Scopes:** Read with `monitoring.read`, change with `monitoring.write`. See [Tokens and scopes](../tokens-and-scopes.md#scopes).
[Cost events](#cost-events) 1 · [Cost items](#cost-items) 4 · [Price changes](#price-changes) 1
Every endpoint below takes a token in the `Authorization: Bearer` header and answers JSON. Errors use the shared format in [Errors](../errors.md). Base address: `https://api.infranest.io/api`. ## Cost events ### List cost events {#get-organizations-organization-cost-events}
`GET` `/organizations/{organization}/cost-events` **Scope:** `monitoring.read` · **Changes data:** no Money spent on a date, such as registrations, renewals, transfers and purchases, newest first, up to 500 entries. Narrow with `entity_type`, `entity_id`, `from` and `to`. Requires a plan that includes cost reporting. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `entity_type`
body | string | | | `entity_id`
body | integer | | | `from`
body | string | Must be a valid date. | | `to`
body | string | Must be a valid date. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl "https://api.infranest.io/api/organizations/42/cost-events" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json [] ```
## Cost items ### List cost items {#get-organizations-organization-cost-items}
`GET` `/organizations/{organization}/cost-items` **Scope:** `monitoring.read` · **Changes data:** no The recurring costs you recorded on one resource. `entity_type` is required, and `entity_id` too unless `entity_type` is `organization`, which lists costs that belong to the whole organization. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `entity_type`
body · required | string | | | `entity_id`
body | integer | | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl "https://api.infranest.io/api/organizations/42/cost-items?entity_type=%3Centity_type%3E" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json [] ```
--- ### Create a cost item {#post-organizations-organization-cost-items}
`POST` `/organizations/{organization}/cost-items` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Records a recurring cost with a `label`, `amount`, `currency` and optional `period` (default monthly) on a resource (`entity_type`, `entity_id`), or on the whole organization with `entity_type` `organization`. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `entity_type`
body · required | string | | | `entity_id`
body | integer | Absent for an org-level cost, which belongs to no object. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`idempotency_in_progress`](../errors.md#idempotency_in_progress), [`validation_failed`](../errors.md#validation_failed), [`idempotency_key_reused`](../errors.md#idempotency_key_reused), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X POST "https://api.infranest.io/api/organizations/42/cost-items" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{"entity_type":"organization","label":"Uptime SMS credits","amount":9,"currency":"EUR"}' ``` **Response** · 201 — Created ```json { "organization_id": 1, "label": "Uptime SMS credits", "amount": "9.00", "currency": "EUR", "period": "monthly", "updated_at": "2026-01-15T12:00:00.000000Z", "created_at": "2026-01-15T12:00:00.000000Z", "id": 2 } ```
--- ### Update a cost item {#patch-organizations-organization-cost-items-costitem}
`PATCH` `/organizations/{organization}/cost-items/{costItem}` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Changes the cost’s `label`, `amount`, `currency` and `period`. `label`, `amount` and `currency` are required on every update; an omitted `period` resets to monthly. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `costItem_id`
path · required | integer | The costItem's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`validation_failed`](../errors.md#validation_failed), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X PATCH "https://api.infranest.io/api/organizations/42/cost-items/1" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{"label":"Status page SMS credits","amount":15,"currency":"EUR"}' ``` **Response** · 200 ```json { "id": 1, "organization_id": 1, "cost_itemable_type": null, "cost_itemable_id": null, "label": "Status page SMS credits", "amount": "15.00", "currency": "EUR", "period": "monthly", "created_at": "2026-01-15T12:00:00.000000Z", "updated_at": "2026-01-15T12:00:00.000000Z" } ```
--- ### Delete a cost item {#delete-organizations-organization-cost-items-costitem}
`DELETE` `/organizations/{organization}/cost-items/{costItem}` **Scope:** `monitoring.write` · **Changes data:** yes — only where API writes are switched on for the organization Deletes the recorded cost. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `costItem_id`
path · required | integer | The costItem's ID. | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`write_disabled`](../errors.md#write_disabled), [`organization_suspended`](../errors.md#organization_suspended), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl -X DELETE "https://api.infranest.io/api/organizations/42/cost-items/1" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 204 — no content
## Price changes ### List price changes for a resource {#get-organizations-organization-price-changes}
`GET` `/organizations/{organization}/price-changes` **Scope:** `monitoring.read` · **Changes data:** no How one resource’s price has changed over time, newest first, up to 100 entries. `entity_type` and `entity_id` are required. | Field | Type | Notes | |---|---|---| | `organization_id`
path · required | integer | Your organization's ID. | | `entity_type`
body · required | string | | | `entity_id`
body · required | integer | | **Errors:** [`unauthenticated`](../errors.md#unauthenticated), [`scope_missing`](../errors.md#scope_missing), [`wrong_organization`](../errors.md#wrong_organization), [`test_token_required`](../errors.md#test_token_required), [`test_token_sandbox_only`](../errors.md#test_token_sandbox_only), [`permission_denied`](../errors.md#permission_denied), [`not_found`](../errors.md#not_found), [`rate_limited`](../errors.md#rate_limited)
**Request** ```sh curl "https://api.infranest.io/api/organizations/42/price-changes?entity_type=%3Centity_type%3E&entity_id=16" \ -H "Authorization: Bearer $INFRANEST_TOKEN" \ -H "Accept: application/json" ``` **Response** · 200 ```json [ { "id": 2, "organization_id": 1, "priceable_type": "App\\Models\\Domain", "priceable_id": 1, "label": "northwind.com", "field": "renewal_price", "old_amount": "13.5000", "old_currency": "EUR", "old_interval": "yearly", "old_interval_count": 1, "new_amount": "12.5000", "new_currency": "EUR", "new_interval": "yearly", "new_interval_count": 1, "source": "api", "changed_by_user_id": null, "observed_at": "2025-12-02T12:00:00.000000Z", "effective_from": "2025-12-02T00:00:00.000000Z", "created_at": "2026-01-15T12:00:00.000000Z", "updated_at": "2026-01-15T12:00:00.000000Z", "changed_by": null } ] ```