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

# Declarations

> How an app adopts a connector template, and when that declaration is confirmed.

A declaration is an owned meaning: a namespace, a kind, a key, a meaning, and a
status. A metric expression is the meaning of a declaration whose kind is
`metric`. Erdo returns that meaning only when the declaration is confirmed.

`PUT /v1/declarations` upserts one declaration for the caller's organization.
Sending the same namespace, kind, and key again updates that row.

```json theme={null}
{
  "namespace": "app-a",
  "kind": "metric",
  "key": "spend",
  "meaning": "sum(amount)",
  "status": "confirmed",
  "reasoning": "the synced column is amount",
  "confidence": "1",
  "scope": { "source": "google_ads", "table": "google_ads_campaign" }
}
```

`scope` names the only source and table this declaration covers. Omit it, or
set both `source` and `table`. One without the other is rejected. A declaration
does not apply to any other source or table, and a declaration with no scope
does not apply to a table read.

`status: "confirmed"` means the owning app committed this declaration and merged
it through a human-reviewed pull request. Erdo stores that status as
`verification_status: approved`. It does not infer it. Any other status is a
draft. A draft is kept and does not change a resolved value. A model proposal
is a draft.

Each connector ships templates for its standard metrics. A template is code
for one source and table. It is not a stored declaration and it is not
confirmed. A read uses a confirmed declaration for that source, table, and
key, then the template, then reports the measure as not set.

To adopt, send the same request with `"adopt": true` and the template's scope.
Leave `meaning` empty to take the template expression, or set `meaning` to
override it. Send `status: "confirmed"` only after that adoption is merged
through a human-reviewed pull request in the app's repository.

Two confirmed meanings for the same namespace, kind, key, source, and table
return `conflicting definitions`. A missing input stays null. It is not
reported as 0.

## From the CLI and MCP

`erdo declarations upsert` sends the same request from a terminal or CI, and
the `erdo_upsert_declaration` MCP tool does the same for an agent. Both take
`--namespace`, `--kind`, `--key`, `--meaning`, `--status`, `--source` and
`--table` (together), and `--adopt`.


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