Skip to content

Reporting API schemas ​

These are the component schemas of api/reporting/openapi.yaml, the document Reporting API endpoints is rendered from. An operation there names the schema of each body it reads and each body it answers with, and links it here.

Schemas ​

CreateProject ​

The project to register. Its (cloud, external_id) pair has to be one the registry does not hold yet.

PropertyTypeRequiredDescription
cloudstringyesThe installation the project lives in, os-prod-eu1 for example. A virtual project carries its platform here, and no real project carries meta or partner.
external_idstringyesThe project as its cloud names it.
metadataobjectnoWhatever else is worth keeping about the project. A registration that leaves it out stores the empty object. The stored document is bounded at 65536 bytes as the database normalizes it: a number a body spells as an exponent is stored, and answered, spelled out. A write whose document is past the bound is answered 422 and stores nothing.
namestringnoWhat the project is called.
platformstringyesThe platform the project lives on, openstack for example. meta and partner are reserved for the two kinds of virtual project that own no resources: the meta-project and the partner.

CreateRelation ​

The relation to create. It leaves the project the path names, so only the other end is given here.

PropertyTypeRequiredDescription
metadataobjectnoWhatever else is worth keeping about the relation. A creation that leaves it out stores the empty object. The member pricing_adjustments is accepted as a non-empty array of at most 64 objects with type (one of discount, kickback, surcharge, project_discount), rate (a decimal string from 0 to 1 with at most six fractional digits, never a number), scope (all, a platform, or platform.resource_type, in lower-case letters, digits and underscores) and an optional description of at most 500 characters, and no other members. The rule enforced is the schema internal/core/adjustment/adjustments_schema.json, which the rating engine reads the array by. An array the schema refuses is answered 422 with one field error per violation, located as body.metadata.pricing_adjustments.<index>.<member>. The stored document is bounded at 65536 bytes as the database normalizes it: a number a body spells as an exponent is stored, and answered, spelled out. A write whose document is past the bound is answered 422 and stores nothing.
relation_typestringyesWhat the relation means. infrastructure_tenant attributes the cost of the target to the source and is the default attributing type. member_of groups the source under a meta-project (platform meta), and managed_by places the source under a partner (platform partner); neither of the two ever attributes cost. The field is a free string, so any other type is stored as it arrives.
target_idstring, uuid, ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$yesThe project the relation reaches. It has to be registered, and it cannot be the project the relation leaves.
valid_fromstring, date-timenoWhen the relation starts being valid. It defaults to the instant the relation is written.

DeadLetterList ​

One page of dead-lettered events.

PropertyTypeRequiredDescription
itemsarray of DeadLetteredEventyesThe refused items of this page, ordered by received_at and id.
next_cursorstring or nullyesWhere the next page starts, passed back as cursor. It is null on the last page.

DeadLetteredEvent ​

One ingest item this API refused, as the dead-letter table holds it.

PropertyTypeRequiredDescription
idstring, uuidyesThe dead-letter row. A refused item has no event id this API can trust, so the row's own id is what names it.
rawanyyesThe item as it was submitted, with NUL characters scrubbed at ingest. Nothing is constrained here: what a collector sent need not be a JSON object, and this member carries whatever it was.
reasonstringyesWhy ingestion refused the item, a schema violation for example, prefixed the way the ingest response reports it.
received_atstring, date-timeyesWhen this API refused the item.

EventInput ​

One canonical event. The members below are described rather than constrained; the normative schema is roadmap/00-conventions.md section 4.

PropertyTypeRequiredDescription
cloudanynoThe installation the resource lives in, os-prod-eu1 for example. meta and partner are the clouds of the virtual projects, so an item carrying either refuses the item as well.
event_idanynoGlobally unique idempotency key of 1 to 256 characters. An event id resubmitted with the same timestamp counts as a duplicate.
event_typeanynoWhat happened, written resource.action with an optional phase, for example compute.instance.create.end.
payloadanynoThe normalized payload envelope: the state at or after the event, the full replacement size when it changed, and optional raw provider data.
platformanynoThe platform the resource lives on, openstack for example. meta and partner name the two kinds of virtual project, which own no resources; an item carrying either refuses the item.
project_idanynoThe project owning the resource at or after this event.
resource_idanynoThe resource this event is about.
resource_typeanynoThe kind of resource, instance or volume for example.
sourceanynoWhere the event came from. The stored event always reports the pipeline that ingested it, so a collector cannot mark its events as reconciliation output. The member may be left out; a value outside collector and reconciliation refuses the item.
timestampanynoWhen the event happened, ISO 8601 with a timezone.

EventList ​

One page of stored events.

PropertyTypeRequiredDescription
itemsarray of StoredEventyesThe events of this page, ordered by timestamp and event id.
next_cursorstring or nullyesWhere the next page starts, passed back as cursor. It is null on the last page.

EventStatsItem ​

One group of the event counts: the bucket it falls in, the values its dimensions carry, and how many events carry all of them.

PropertyTypeRequiredDescription
bucketstring, date-timeyesWhen the bucket starts, in UTC. A bucket covers interval from there on, the start inclusive and the end exclusive.
cloudstringyesThe installation the counted events came from.
countinteger, int64yesHow many events the group holds.
event_typestringyesThe type the counted events carry.
sourcestringnoWhich pipeline produced the counted events, collector or reconciliation. The member is there exactly when group_by names source.

EventStatsList ​

The event counts of one window.

PropertyTypeRequiredDescription
itemsarray of EventStatsItemyesThe groups, ordered by bucket, cloud, event type, and source. It is the empty array when the window holds no event.

IngestResult ​

What one ingest call did with the batch it was given.

PropertyTypeRequiredDescription
acceptedintegeryesHow many events the call stored.
duplicatesintegeryesHow many items the database already held.
rejectedarray of RejectedEventyesThe items the call refused, one entry each.

Lifecycle ​

One resource, its event history, and the billable intervals that history folds into. resource is always there: a resource this API holds no projection row for is answered 404 rather than with an empty lifecycle.

The two halves are derived from two different event sets. events and intervals carry the history this token may read, while resource is the projection row, folded from every event the resource has under no scope. On a resource that changed projects the row therefore reports a created_at from before the reader owned it, and the first interval starts at the transfer.

PropertyTypeRequiredDescription
eventsarray of StoredEventyesThe full history the fold ran on, ordered by (timestamp, received_at, event_id).
intervalsarray of LifecycleIntervalyesThe billable intervals the history implies, oldest first. Two billable changes at the same instant leave no interval between them, so a resource created and deleted at one instant has none at all.
resourceResourceyesOne resource as the projection holds it: what its event history says it is right now.
warningsarray of stringyesWhat the fold could not trust, one entry each. A history whose first event is not a create carries history_starts_without_create.

LifecycleInterval ​

One half-open span [from, to) over which nothing billable about a resource changed.

PropertyTypeRequiredDescription
fromstring, date-timeyesWhen the interval starts, the inclusive bound.
project_idstringyesThe project owning the resource over the interval.
sizeobjectyesThe size the resource had over the interval.
statestringyesThe state the resource was in over the interval.
tostring or null, date-timeyesWhen the interval ends, the exclusive bound. It is null while the interval is open, which the last interval of a living resource is.

Problem ​

RFC 9457 problem detail. Every error response in this API uses this shape, served as application/problem+json.

PropertyTypeRequiredDescription
detailstringnoHuman-readable explanation specific to this occurrence.
errorsarray of objectnoPer-field details, set when the problem is a validation failure.
statusintegeryesThe HTTP status code of this response.
titlestringyesShort human-readable summary of the problem type.
typestringyesURI reference identifying the problem type.

Project ​

One registered project. The registry is keyed by (cloud, external_id), and id is what the other operations address the project by.

PropertyTypeRequiredDescription
cloudstringyesThe installation the project lives in, os-prod-eu1 for example. A virtual project carries its platform here, and no real project carries meta or partner.
created_atstring, date-timeyesWhen the project was registered.
external_idstringyesThe project as its cloud names it, which is the id an event carries.
idstring, uuidyesThe project, as this API names it.
metadataobjectyesWhatever else was stored about the project. It is the empty object for a project registered without any.
namestring or nullyesWhat the project is called, null for a project registered without a name.
platformstringyesThe platform the project lives on, openstack for example. meta and partner are reserved for the two kinds of virtual project that own no resources: the meta-project and the partner.

ProjectActivity ​

What one resource type of a project did inside the window of a summary.

PropertyTypeRequiredDescription
active_nowintegeryesHow many resources of the type the project holds right now, counted off the projection rows that are not deleted. It describes the present rather than the window, so a type the window saw nothing of still reports what the project runs of it today.
createdintegeryesHow many resources of the type began their life inside the window.
deletedintegeryesHow many resources of the type ended their life inside the window.
resource_typestringyesThe kind of resource this row is about.
total_minutesinteger, int64yesHow long the resources of the type ran inside the window, in whole minutes, truncated. An interval still open is counted up to the instant of the request, so a window reaching into the future carries no time that has not been served yet.

ProjectList ​

One page of registered projects.

PropertyTypeRequiredDescription
itemsarray of ProjectyesThe projects of this page, ordered by cloud and external id.
next_cursorstring or nullyesWhere the next page starts, passed back as cursor. It is null on the last page.

ProjectRef ​

Which project an answer is about, as much of it as a project-scoped read carries. The registry row itself — the name, the operator-set metadata, the platform, and when it was registered — is what getProject serves, and reading that takes read_all.

PropertyTypeRequiredDescription
cloudstringyesThe installation the project lives in, os-prod-eu1 for example.
external_idstringyesThe project as its cloud names it, which is the id an event carries.
idstring, uuidyesThe project, as this API names it.

ProjectSummary ​

One project and what its resource types did inside one window.

PropertyTypeRequiredDescription
projectProjectRefyesWhich project an answer is about, as much of it as a project-scoped read carries. The registry row itself — the name, the operator-set metadata, the platform, and when it was registered — is what getProject serves, and reading that takes read_all.
resource_typesarray of ProjectActivityyesOne row per resource type the project has events or resources of, ordered by resource type. It is the empty array for a project with neither.

RebuildRequest ​

Which resources to replay. A member left out filters nothing, so an empty object rebuilds every resource the events table knows.

PropertyTypeRequiredDescription
cloudstringnoReplay only the resources of this cloud.
resource_typestringnoReplay only the resources of this type.

RebuildResult ​

What one rebuild replayed.

PropertyTypeRequiredDescription
rebuiltintegeryesHow many resources were replayed.

RegisterResourceType ​

The size schema to register for a resource type.

PropertyTypeRequiredDescription
size_schemaobjectyesA JSON Schema draft 2020-12 document. It is compiled before it is stored, so the document a registration accepts is exactly the one ingestion can apply later.

RejectedEvent ​

One refused item and the reason it was refused.

PropertyTypeRequiredDescription
event_idstringyesThe event id the item carried. It is the empty string for an item that carried none, which is why the index is what identifies the item.
indexintegeryesThe item's position in the submitted batch, counted from zero.
reasonstringyesWhy the item was refused, for example "size_schema: 'vcpus' is a required property" or 'schema: platform: "meta" is a virtual platform, which never carries resources'.

RelatedProject ​

One project a traversal reached.

PropertyTypeRequiredDescription
depthintegeryesHow many relations lie between the project the walk started from and this one.
patharray of string, uuidyesThe relation ids from the start to this project in walk order, so it holds depth of them.
projectProjectyesOne registered project. The registry is keyed by (cloud, external_id), and id is what the other operations address the project by.
relation_typestringyesThe type of the relation the walk arrived on.

RelatedProjectList ​

The projects one traversal reached.

PropertyTypeRequiredDescription
itemsarray of RelatedProjectyesThe projects the walk reached, in the order it visited them.

Relation ​

One relation between two projects. It is valid at t iff valid_from <= t AND (valid_to IS NULL OR valid_to > t), and it is closed rather than deleted, so a read at an earlier instant still finds it.

PropertyTypeRequiredDescription
created_atstring, date-timeyesWhen the relation was written.
idstring, uuidyesThe relation, as this API names it.
metadataobjectyesWhatever else was stored about the relation. It is the empty object for a relation created without any. The member pricing_adjustments, when present, holds a non-empty array of at most 64 objects with type (one of discount, kickback, surcharge, project_discount), rate (a decimal string from 0 to 1 with at most six fractional digits, never a number), scope (all, a platform, or platform.resource_type, in lower-case letters, digits and underscores) and an optional description of at most 500 characters, and no other members. The schema internal/core/adjustment/adjustments_schema.json decided the array at the write, and the rating engine reads it by that same schema.
relation_typestringyesWhat the relation means. infrastructure_tenant attributes the cost of the target to the source and is the default attributing type. member_of groups the source under a meta-project (platform meta), and managed_by places the source under a partner (platform partner); neither of the two ever attributes cost. The field is a free string, so any other type is stored as it arrives.
source_idstring, uuidyesThe project the relation leaves.
target_idstring, uuidyesThe project the relation reaches.
valid_fromstring, date-timeyesWhen the relation starts being valid, the inclusive bound.
valid_tostring or null, date-timeyesWhen the relation stops being valid, the exclusive bound. It is null while the relation is open.

RelationList ​

The relations of one project at one instant.

PropertyTypeRequiredDescription
itemsarray of RelationyesThe relations valid at that instant, ordered by created_at and id.

Resource ​

One resource as the projection holds it: what its event history says it is right now.

PropertyTypeRequiredDescription
cloudstringyesThe installation the resource lives in.
created_atstring or null, date-timeyesWhen the resource was created, as the projection folded it from the resource's whole history. It is null for a history that never showed a create. The projection is not scoped to the reading token, so on a resource that changed projects this is the create of the project it came from and predates the reader's ownership: what a project is billed for is the lifecycle's intervals, never created_at paired with deleted_at.
deleted_atstring or null, date-timeyesWhen the resource was deleted, null while it lives.
first_event_atstring, date-timeyesWhen the earliest event folded into this row happened. Every row carries it, so it answers for a resource whose history opens with something other than a create and leaves created_at null; where the history does open with a create the two hold the same instant. It is unscoped the way created_at is, so on a resource that changed projects it is the first event of the project it came from and predates the reader's ownership. It says when the resource entered the record, not what anyone owes: what a project is billed for is the lifecycle's intervals.
last_event_atstring, date-timeyesWhen that event happened.
last_event_typestringyesThe type of the newest event folded into this row. It is a sync.create, sync.update, or sync.delete when the newest thing that happened to the resource was a correction by the reconciliation framework rather than a report by a collector.
last_payloadobject or nullyesThe payload envelope of that event, member for member as it was stored, and null for a row that holds none.
platformstringyesThe platform the resource lives on.
project_idstringyesThe project owning the resource now.
resource_idstringyesThe resource itself, as its cloud names it.
resource_typestringyesThe kind of resource.
sizeobjectyesThe size the resource has now, member for member as its events reported it. It is the empty object for a history that reported no size.
statestringyesThe state the resource is in now. A deleted resource carries deleted, which the server sets itself rather than reading it off the delete event.

ResourceList ​

One page of current resources.

PropertyTypeRequiredDescription
itemsarray of ResourceyesThe resources of this page, ordered by cloud, resource type, and resource id.
next_cursorstring or nullyesWhere the next page starts, passed back as cursor. It is null on the last page.

ResourceStatsItem ​

One group of the resource counts: the values its dimensions carry, and how many resources carry all of them.

PropertyTypeRequiredDescription
cloudstringyesThe installation the counted resources live in.
countinteger, int64yesHow many resources the group holds.
platformstringnoThe platform the counted resources live on. The member is there exactly when group_by names platform.
project_idstringnoThe project owning the counted resources, named the way its cloud names it. The member is there exactly when group_by names project_id.
resource_typestringyesThe kind of resource that was counted.
statestringnoThe state the counted resources are in. The member is there exactly when group_by names state.

ResourceStatsList ​

The resource counts of one grouping.

PropertyTypeRequiredDescription
itemsarray of ResourceStatsItemyesThe groups, ordered by cloud, resource type, state, platform, and project id. It is the empty array when the grouping counts no resource at all.

ResourceType ​

One registered resource type and the size schema the sizes reported for it are validated against.

PropertyTypeRequiredDescription
platformstringyesThe platform the resource type belongs to.
resource_typestringyesThe resource type within that platform.
size_schemaobjectyesThe registered JSON Schema draft 2020-12 document.
updated_atstring, date-timeyesWhen the schema was last written.

ResourceTypeList ​

The registered resource types.

PropertyTypeRequiredDescription
itemsarray of ResourceTypeyesThe resource types, ordered by platform and resource type.
next_cursorstring or nullyesWhere the next page starts. It is always null today: the registry holds one row per resource type, so every registration fits into one answer. The registry list stays a single page, while the query lists page with cursors.

StoredEvent ​

One event as the events table holds it: what was submitted, plus the instant this API stored it.

PropertyTypeRequiredDescription
cloudstringyesThe installation the resource lives in.
event_idstringyesThe idempotency key the event was submitted under.
event_typestringyesWhat happened, written resource.action with an optional phase, for example compute.instance.create.end. The reconciliation framework writes the second family, sync.create, sync.update, and sync.delete: a correction is about no one service, so it names none. source is the member to branch on rather than the prefix — it is reconciliation for exactly those events.
payloadobject or nullyesThe normalized payload envelope, member for member as it was stored. It is null for an event stored without one, which a delete event may be. The members are not constrained here: an envelope keeps the fields a provider sent beyond the ones this API names.
platformstringyesThe platform the resource lives on.
project_idstringyesThe project owning the resource at or after this event.
received_atstring, date-timeyesWhen this API stored the event.
resource_idstringyesThe resource the event is about.
resource_typestringyesThe kind of resource the event is about.
sourcestringyesWhich pipeline produced the event, collector or reconciliation. It is what the server recorded rather than what the submitter claimed.
timestampstring, date-timeyesWhen the event happened.

SyncRequest ​

When the run happens. The member is optional, and a request that leaves it out, like one that carries no body at all, syncs at wall time.

PropertyTypeRequiredDescription
atstring, date-timenoRun the sync at this instant instead of at wall time: the run's sync_runs row starts here, and every correction the run books carries this timestamp. The deployment has to set TALLY_REPORTING_SYNC_ALLOW_AT for the member to be accepted. It exists for a development deployment reconciling a simulated cloud, whose clock is not the wall clock.

SyncResult ​

What one sync run did.

PropertyTypeRequiredDescription
statsSyncStatsyesThe tally of one sync run, which is one that finished clean.
sync_run_idstringyesThe id of the sync_runs row this run wrote. It is what an operator reads the run back by, and what the synthetic event ids of the run are derived from.

SyncStats ​

The tally of one sync run, which is one that finished clean.

PropertyTypeRequiredDescription
createdintegeryesHow many resources the run reported to the projection as new, one synthetic event each.
deletedintegeryesHow many it reported as gone.
updatedintegeryesHow many it corrected the state, size, or owner of.

UpdateProject ​

What to change about a project. A member the request leaves out stays as it is, so at least one of them has to be present.

PropertyTypeRequiredDescription
metadataobjectnoThe metadata the project carries from now on. It replaces the stored object wholesale rather than being merged into it, so a request carrying it carries every member the project keeps. The stored document is bounded at 65536 bytes as the database normalizes it: a number a body spells as an exponent is stored, and answered, spelled out. A write whose document is past the bound is answered 422 and stores nothing.
namestringnoWhat the project is called from now on.

UpdateRelation ​

What to change about a relation. A member the request leaves out stays as it is, so at least one of them has to be present.

PropertyTypeRequiredDescription
metadataobjectnoThe metadata the relation carries from now on. It replaces the stored object wholesale rather than being merged into it, so a request carrying it carries every member the relation keeps. The pricing_adjustments of a relation are fixed for its lifetime. A document whose member differs from the stored one, by being added, dropped, reordered or changed in any value, is answered 409. To change the other members, send the member back exactly as the relation answers it; to change the adjustments, close the relation and create a successor. The stored document is bounded at 65536 bytes as the database normalizes it: a number a body spells as an exponent is stored, and answered, spelled out. A write whose document is past the bound is answered 422 and stores nothing.
valid_tostring, date-timenoWhen the relation stops being valid. It has to be after valid_from. The member is not nullable: an open relation is closed here and a closed one gets its close instant corrected, while reopening a closed relation is not supported.

Uuid ​

A string, format uuid, matching ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$.