# HuMetric > Learn how to use the HuMetric API for entity metrics, signal processing, and semantic queries. HuMetric is a metric engine that turns free-text signals into calibrated, temporally-decaying entity metrics. Everything below is reached through one HTTP API. Base URL: https://api.gethumetric.com Auth: Authorization: Bearer hm_live_ ## Concepts - **Entity**: The thing you measure — an agent, a user, a task. Everything in HuMetric hangs off an entity and the ID you give it. - **Signal**: A piece of evidence about an entity: free text or structured data. You send signals; HuMetric reads them. - **Metric**: A calibrated 0–1 score HuMetric extracts from signals. Each carries a confidence and fades as it ages. - **Pack**: Your scoring rules. A pack declares which metrics to extract for an entity type — define it once, reuse it forever. - **Confidence**: How sure HuMetric is about a value. It is recorded once and never rewritten — but its weight decays as the evidence ages, so a stale score quietly stops counting. - **Consent**: A pack can mark a metric sensitive. Those values stay hidden until the entity has granted the matching consent scope, and disappear again the moment it is revoked. ## Getting started in four calls 1. `POST /v1/packs` — Tell HuMetric what to measure for an entity type — e.g. agents get code_quality and helpfulness. 2. `POST /v1/entities` — Register the thing you’ll track. Signals are rejected until the entity exists. 3. `POST /v1/signals` — Feed evidence as it happens. HuMetric extracts metrics and updates them in the background. 4. `GET /v1/entities/{id}/metrics` — Pull one entity’s live metrics, or query in plain language across all of them. ## Docs - [Full API reference (plain text)](https://gethumetric.com/en/llms-full.txt): The whole reference as plain text: concepts, conventions, every endpoint with its response, errors, limits. - [API reference (HTML)](https://gethumetric.com/en/docs) - [OpenAPI](https://api.gethumetric.com/openapi.json): The machine-readable spec, served by the API itself. Note that most routes do not declare a response schema there, so response bodies are only complete on this page. ## Articles - [A ready-made Metric Pack for contact centres](https://gethumetric.com/en/blog/ready-made-metric-pack-for-contact-centres): A real seven-metric pack, the GDPR consent gate, and the numbers from an actual run. - [Defining dealer churn risk with Pack Wizard](https://gethumetric.com/en/blog/measuring-dealer-churn-risk-with-pack-wizard): When you do not know what to measure: generating a working pack from a plain description. - [Turning dealer visit notes into automatic scores](https://gethumetric.com/en/blog/turning-dealer-visit-notes-into-automatic-scores): Turning free-text field notes into traceable performance metrics. - [Why temporal decay beats a static score](https://gethumetric.com/en/blog/why-temporal-decay-beats-a-static-score): confidence versus effective_confidence, and why stale evidence should quietly stop counting. ## Things to know The tables these rules refer to — which fields accept camelCase, the per-endpoint ceilings — are in https://gethumetric.com/en/llms-full.txt. - **Writes are asynchronous**: POST /v1/signals answers 202 with a signal_id and a trace_url before any work happens. The status it returns is "received" — never "queued". Extraction runs in the background and moves the signal to "completed" or "failed"; a retried signal goes back to "received". Metrics are never up to date in the same call that produced them, so poll the signal or re-read the entity. - **Pagination**: Most list endpoints take limit and offset and answer with items, total, limit, offset — but not all of them, so check the shape per endpoint below. Metric history returns points instead of items. GET /v1/packs, GET /v1/consent/{entity_id} and GET /v1/metrics/pending-review return a bare JSON array with no envelope and no paging at all. GET /v1/api-keys returns {api_keys: […]} with no total. Where limit is accepted, asking above the ceiling is clamped silently rather than rejected. - **Timestamps**: Every timestamp in and out is ISO 8601. Send UTC; a value without a timezone is read as UTC. occurred_at may not be in the future. - **Re-sending a signal**: Idempotency is the Idempotency-Key request header, not a body field. Send the same header value again for the same entity within 24 hours and you get 200 with the original signal and its metrics instead of a second queue entry — that is what makes a webhook retry safe. Two things to be careful about. external_id on its own does not give you this: the replay check only runs when the header is present, and because both write to the same unique column, re-sending an external_id you have already used for that entity fails with 500 rather than returning the original. The same is true of a header value replayed after the 24-hour window has passed. So treat an idempotency value as single-use per entity per day: send it as the header, keep it unique, and do not reuse yesterday’s. - **confidence vs effective_confidence**: confidence is what was recorded at the time — the honest line to plot. effective_confidence applies exponential temporal decay at read time, with a half-life of 365 days: what that evidence is still worth today. They are not interchangeable; rank on the effective one, chart the raw one. Note that POST /v1/signals results and GET /v1/metrics/pending-review carry the raw confidence only. - **Field naming**: Responses are always snake_case. Requests are mostly snake_case too: camelCase is accepted only on the specific fields listed below, because each alias was added by hand rather than by a naming rule. Anything not on that list is rejected with 422 — entityId, entityType and externalId on POST /v1/signals are the ones people hit first. Send snake_case everywhere and none of this matters.