# Credentials (/docs/integrations/api/credentials)



This page is for the workspace **administrator** who issues the credential.
The developer's side is [Automation API](./overview).

A **connected system** is another piece of software that works with your
workspace on its own: an ERP, a data warehouse, a nightly job. It signs in
with a credential of its own rather than with somebody's account, pushes data
into a dataset, starts a run, and collects the results on its own schedule.

## What a connected system can do [#what-a-connected-system-can-do]

What it may do is decided entirely by the access you grant its credential:
**read the workspace**, **write data** into a dataset of an analytic app,
**run a pipeline**, and **read results** as a downloadable export.

That is the whole surface. Whatever access you tick, a connected system cannot
create or delete apps, change a pipeline, edit a Visualisation, invite people
or change workspace settings.

## Issuing one [#issuing-one]

Open the **Access** page and its **API credentials** tab, beside the members.
The tab is **admin-only**: a member is not offered it, and every request behind
it is refused for anyone but an admin. A credential is a
**workspace asset**, not a personal one - it keeps working after whoever
created it leaves. The list still names the person who issued it and marks the
credential **Former member** once that person is gone, so you have a prompt to
review whether the integration is still wanted.

**New credential** asks for a name, an optional description, how long the
credential lasts (30, 90, 180 or 365 days; 365 unless you choose otherwise), and
the access to grant. Name it after the system it is for ("ERP nightly import" rather than
"test"): that name is what the audit trail shows every time the integration
writes something.

Creating it produces a **Client ID**, which identifies the credential and is
safe to show, and a **Client secret**, which proves the system is that
credential. **The secret is shown once**, in the dialog that appears right
after you create the credential, and nothing can show it again - it is not
stored anywhere anyone, including an admin, can read it back. If it is lost,
rotate the credential to issue a new one. The dialog copies each one, or both at once as the environment variables
`OVIDENS_CLIENT_ID` and `OVIDENS_CLIENT_SECRET`, and **I've stored it** closes
it and discards the secret from the page.

Hand both to whoever builds the integration, along with one link: [Automation
API](./overview). Everything after that - how the system signs in, which
endpoints it calls, what the file has to look like - is written down there.

## What the access options mean [#what-the-access-options-mean]

Each option grants one kind of work and nothing else. The picker also prints
the technical name each one carries in the API, which is what the developer
will ask you about.

| Access                      | What it lets the system do                                  |
| --------------------------- | ----------------------------------------------------------- |
| **Read the workspace**      | List apps, nodes and their configuration.                   |
| **Write data**              | Import and change the rows of a dataset.                    |
| **Write indicator values**  | Enter and clear collected indicator values.                 |
| **Run published pipelines** | Run an app's published configuration.                       |
| **Run drafts**              | Run unpublished configuration that nobody has reviewed yet. |
| **Read results**            | Query and export the results of a run.                      |
| **Publish**                 | Change what every person in this workspace sees.            |

Two badges tell you how to read that list:

* **Elevated** marks an option that reaches beyond reading and running what
  the workspace has **published** - running an unreviewed draft, or
  publishing, which changes what everyone sees. A new credential never arrives
  with one; grant it only when the system genuinely needs it.
* **Not in effect yet** marks an option nothing checks today. It can be
  granted, stored and shown, but granting it changes nothing an administrator
  could observe. The badge disappears for an option as soon as that option
  starts taking effect.

**Edit access** changes the grant of an existing credential. Nothing has to be
re-issued: the change applies from the credential's very next request, and
taking access away binds even on a token the system is already holding.

## Rotating the secret [#rotating-the-secret]

**Rotate secret** issues a second secret without breaking anything: the secret
in use today keeps working alongside the new one, so you can roll the new one
out at your own pace. A credential never carries more than two secrets, so the
**next** rotation is what retires the older one - rotating twice is the
deliberate "stop accepting the old secret", and the dialog says so before you
confirm.

Rotate when a secret may have been exposed, when the person who set the
integration up leaves, before the credential expires, or on whatever schedule
your own policy sets. The credential's details show when the current secret was
created and when the previous one was last used, so you can watch the old secret go quiet
before retiring it.

A rotation also sets a **new expiry** - the dialog asks how long, as creating
one does - and counts as confirming the credential's access (below).

## Expiry and confirming access [#expiry-and-confirming-access]

Every credential **expires**, at most 365 days after it was created or last
rotated. On the day it expires the connected system is refused, and the only
way back is to **rotate** it, which sets a new expiry. Rotate before then and
nothing stops.

Every **90 days** somebody who manages credentials must also **attest** it:
confirm that the system still needs the access it holds. **Attest** in the
credential's menu lists its access. You can keep only access you hold yourself across
the whole workspace, so anything you do not hold is shown unticked and is
removed when you attest; untick anything else the system no longer needs. You
never add access this way - **Edit access** does that.

Anybody who manages credentials may attest, whether or not they issued it - so
a credential whose issuer has left is attested by whoever covers it, and keeps
only the access that person holds. Nothing about the credential depends on the
issuer still being a member.

When an attestation is missed the credential keeps working for **14 more
days**, marked **Attestation overdue**. After that it is **Suspended**: the
system is refused until somebody attests it, which restores it at once.
Creating or rotating a credential counts as attesting it.

The credentials table shows when each credential expires or must next be
attested, and marks it from **30 days** ahead of either date; its details also
say who attested it last.
While any credential needs attention, everybody who manages credentials also
sees a notice on the **Apps** page linking here. There is no email about it, so
keep an eye on that notice.

A connected system is told which of the two stopped it - see the error codes in
[Automation API](./overview) - and can ask for both dates in advance.

## Telling whether it is working [#telling-whether-it-is-working]

Four places answer that, and they answer different questions:

* The **Access** tab of the credential's details says what the credential may do: every permission
  its access options give it, and which option gives each one. It holds no role, so it works in
  every shared space and every app in one, including apps created later, and never in anyone's
  personal space. A revoked credential can do nothing.
* **The credentials table** says whether the credential is used at all. **Last
  used** is the last time it authenticated and reads "Never used" until the
  integration's first successful call - the first thing to check when a new
  integration is silent.
* **Activity** says how much it is doing and what it has taken out (below).
* **The audit trail** says what it actually changed: open the **Audit
  Analytics** app, go to **All actions**, and filter **Actor kind** to
  **Integration**. The **Actor** of a machine write is the integration itself,
  under its credential's name, not the administrator who issued it. See
  [Audits](../../administration/audit-trail.mdx).

Credential events themselves - created, secret rotated, access changed,
attested, revoked - are in the same trail, attributed to the administrator who
performed them. A credential expiring or being suspended is in the trail too,
attributed to the platform, since nobody performed it.

Runs are attributed in the place you would look for them: in an app's
**History**, a run a connected system started carries that system's name beside
it, and keeps it after the credential is revoked. A run with no marker was
started by a person or by the assistant, or is old enough that the trail entry
it was marked from has aged out.

## What one integration has actually done [#what-one-integration-has-actually-done]

The **Activity** tab of a credential's details has three parts.

**Request limit** is how many requests per minute that credential may make.
Requests beyond it are refused until the next minute begins, and the system is
told how long to wait. This is the number to quote when whoever built the
integration reports being throttled.

**Volume over the last 30 days** counts runs it started, exports it made and
the rows and data those exports contained, and imports that were applied with
the rows they wrote. A failed import is not counted. These are **volumes, not
costs** - compute is measured for the workspace as a whole, so the **Usage**
tab remains the place to see what was consumed - but an integration whose
export row count doubled last month is where to look first when a bill jumps.

**What this integration took out** lists its exports, newest first: when,
which app and which output, which run the file came from, how many rows and
how large, and whether it succeeded. An export is a read rather than a change,
so it does not appear in the audit trail - this list is the answer to "did
this integration pull something it should not have, and when". A row marked
with an asterisk was cut off at the export size limit and holds only part of
the output; "File removed" means the export succeeded but its file has since
been cleaned up (files go within days, the record is kept for 90 days);
hovering a **Failed** status shows the reason the platform recorded, which is
the string to quote back to whoever built the integration.

## Revoking [#revoking]

**Revoke** stops a credential immediately, including any token it is already
holding: its next request is refused. It cannot be undone, so restoring access
means issuing a new credential and giving the system its new secret.

A revoked credential stays in the list, marked **Revoked** and with nothing left
to change but its key still copyable, and it keeps its name in the audit trail - so the record of
what it did while it was live stays readable.
