Skip to Content

How do I keep the credentials for JSON API endpoints safe when an AI SRE looks into failed deploys?

Tares keeps the credential for a JSON API endpoint on the source as a secret. The API never returns it and exports never include it. Tares makes the polling requests itself and stores each reply as events, so the investigation of failed deploys works on those events. A Postgres source holds its connection string the same way.

How it works

Each source holds its own connection details, and Tares uses them to poll on the source’s schedule.

  • JSON API endpoints. The http_poll connector sends one credential in one header. credential holds the whole value and is stored as a secret, never returned by the API and never exported. credential_header names the header and defaults to Authorization. A bearer token is entered as the full value, for example Bearer followed by the token. An API key goes in a header such as X-API-Key.
  • Other headers. Headers the API wants on every request go in headers, which is not secret. Keep anything sensitive in credential, not in headers.
  • Postgres. The postgres connector takes a connection URL in dsn. It is stored as a secret, redacted in the API and omitted from catalog exports.
  • Events. Tares calls the endpoint and stores one event per item. The payload is stored as received. Your deploy investigation then works on those stored events, such as a deploy id, a status and a service.

For how an AI SRE uses events like these, see AI SRE.

Set it up

  1. Open Sources → Add source → HTTP API (poll). Fill in the method and URL. Enter the credential as one header name and value, which Tares stores as a secret. Add any non-secret headers separately.
  2. Press Discover. Tares calls the API once, shows the reply it got and fills in what becomes an event. Pick the entity key from the fields it saw, then create the source.
  3. Or declare the source in YAML. This example polls a deploy API with an API key sent in X-API-Key:
- name: deploys connector: http_poll poll: 5m config: url: https://api.example.com/v1/readings credential: abc123 # an API key credential_header: X-API-Key event_type: deploy id_field: id text_template: '{id}: {status}' labels: - { name: service, field: service, primary: true } - { name: status, field: status }
  1. Set id_field to the deploy’s own id so a deploy already seen in recent polls is not stored again. Set event_type so trigger filters can match deploy events.
  2. For deploy records in a database, add a Postgres source instead. Enter the Connection URL (dsn), press Discover, pick the table and save. Use a cursor column that only grows, such as updated_at, so changed rows arrive as new events.
  3. Open the source and check Recent events and Fields. Every field seen is listed with its coverage, so you can confirm a status field is reliably present before you build on it.

Details for each connector are on the HTTP API (poll) page and the Postgres table page.

What you get

  • The credential sits in one place, on the source, stored as a secret. It is never returned by the API and never exported.
  • A Postgres dsn is redacted in the API and left out of catalog exports.
  • Tares polls the endpoint itself, so you run no script on your side that would need its own copy of the credential.
  • Failed deploys arrive as events with the fields you choose as labels, such as service and status.
  • A rate-limited or failing API shows up on the source’s health. A 429 or 5xx backs polling off, doubling the wait from the poll interval up to an hour. Any other 4xx appears as a config error with the status and a slice of the reply.

When something else fits

  • If your deploy system calls Tares when a deploy fails, use the webhook connector instead of polling. It is the right fit for systems that call Tares, while http_poll is for APIs Tares calls.
  • http_poll sends one credential in one header. If an API needs more than that, check the endpoint against what a single header can carry before you rely on it.
  • If your deploy data lives in a database table, the Postgres connector reads it directly with a connection URL.

Still stuck? Get help

Last updated on