All documentation
Connectors
The five connector types and what each one needs, getting an OpenAI or Anthropic Admin API key and a GitHub token, what each connector collects, the manual import format, and how hourly syncing works.
A connector is an automated way to fetch evidence instead of typing it in every time. There are five kinds — OpenAI, Anthropic, GitHub, Log lake and Manual. You choose one, supply the credential it needs, and that is it: the credential is encrypted before it reaches our database and can never be read back out in plain text.
Two things catch nearly everyone. OpenAI and Anthropic need an Admin key, not the ordinary API key you use to call the models — an ordinary key is rejected, because the connector reads organisation-wide usage. And Manual needs no credential at all: you add the connector first, and the box for uploading your file appears afterwards.
Vendor steps last checked: 2026-07-29. Provider consoles are redesigned without notice, so each set of steps below also names the setting to look for, not just the path to it.
More detail
What each type needs
- OpenAIAn OpenAI Admin API key. An OpenAI organisation ID is optional, and only matters if your account belongs to more than one organisation. Know more →
- AnthropicAn Anthropic Admin API key, and nothing else. Know more →
- GitHubA GitHub personal access token and the repository, written as
owner/name. Know more → - Log lake (S3-compatible bucket)Credentials for a bucket you already export logs to, plus a short description of how to read those files — which field is the timestamp, which is the identifier, and which kind of evidence each line represents. Clause50 then reads new objects as they land. For teams whose evidence already exists somewhere, in a shape nobody wants to re-key by hand.
- Manual (CSV / JSON upload)No credentials. Add the connector, then use the upload box that appears beneath it. Know more →
If none of these fits, a connector is not the answer. Two cases fall outside it, and both are covered on the API page: evidence your own code can push directly, and evidence from an application whose code you cannot change — a vendor product or a CMS — where you tap the traffic instead.
Some vocabulary, since the rest of this page uses it. An API key is a long secret string that lets one program act on your behalf in another. A token is the same idea under a different name. An Admin key is one that carries authority over a whole organisation account rather than over a single project — which is the distinction the next two sections turn on.
Whatever you supply is sealed before it reaches the database and cannot be read back out in plain text afterwards, including by someone with direct database access. The only thing that can open it is the running server, at the moment it calls the vendor. It is never written to a log, returned by the interface, or shown on a page again.
Getting an OpenAI Admin API key
Start with why an ordinary key will not work. The OpenAI connector reads one address:
GET https://api.openai.com/v1/organization/usage/completions
Read the middle of that: /organization/. It reports usage across your whole OpenAI organisation, which is exactly what makes it useful as evidence — and exactly why an ordinary project key (the sk-proj-… kind used to call the models) cannot read it. A project key has authority over one project and none over organisation-level information. Supplying one produces a connector that turns to error on its first sync with an authorisation failure.
An Admin key is a different kind of key, created in a different place.
- Sign in at platform.openai.com with an account that is an owner of the organisation. Admin keys are an organisation-level capability; an ordinary member seat generally cannot create one.
- Open your organisation settings — the settings scoped to the organisation, not to a project. At the time of writing this is at platform.openai.com/settings/organization/admin-keys.
- Find Admin keys — a section separate from the ordinary API keys page — and create one. Copy it straight away; like every OpenAI key it is shown once and never again.
- In Clause50, open your system's Connectors page, choose the OpenAI type, supply the key as the OpenAI Admin API key, and add the connector.
If the layout has changed: look for settings scoped to the organisation rather than to a project, and within them for a key type described as “admin”, “organisation”, or “service account” — anything whose description mentions administering the organisation or reading usage and billing, rather than calling the models. If your account cannot see that area at all, you are not an owner of the organisation and will need someone who is.
The optional organisation ID. The OpenAI connector also accepts an OpenAI organisation ID, a short identifier beginning org-. Leave it out unless your account belongs to more than one OpenAI organisation. When it is supplied, Clause50 passes it with every request so usage is read from the organisation you meant; when it is absent, OpenAI uses the key's default organisation, which is the right answer for the great majority of accounts. The value is shown on the same organisation settings screen as the admin keys.
Getting an Anthropic Admin API key
Same shape, same reason. The Anthropic connector reads:
GET https://api.anthropic.com/v1/organizations/usage_report/messages
The path says /organizations/, and it means it: this is an organisation-level usage report, not something a key scoped to a single workspace can read. An ordinary API key will be rejected.
- Sign in at console.anthropic.com with an account that administers the organisation.
- Open Settings, and within it the organisation-level section rather than a workspace-level one.
- Find Admin keys and create one. Copy it when it is shown; it is not shown again.
- In Clause50, choose the Anthropic type and supply the key as the Anthropic Admin API key. That is the only thing this connector needs — it sends no organisation identifier.
If the layout has changed: look for settings scoped to the organisation rather than to a workspace, and for a key described as “admin” or as granting access to organisation administration, usage, or cost reporting. If your role in the console cannot reach organisation settings, ask whoever administers the account.
One thing this connector does not record, and why that is deliberate. Anthropic's usage report gives token counts but no count of requests. So the evidence Clause50 writes from it records tokens and models only — it omits the request figure rather than deriving a plausible-looking number from something else. An evidence record is worth having precisely because every number in it came from somewhere real: a missing field is a fact about the source, whereas a field invented to fill the gap is a defect an auditor cannot see. If you compare an OpenAI usage record with an Anthropic one and notice a request count in the first and not the second, that is the reason.
Creating a GitHub personal access token
First, the vocabulary, since this is the step people find most foreign. A repository is one project's source code on GitHub, named as owner/name. A commit is one recorded change to it. A personal access token is a credential you create in your own GitHub settings that lets another application read something on your behalf — you can limit exactly what it reaches, and you should.
The connector reads one thing: the list of commits in the single repository you name. So the token it needs is correspondingly small — a fine-grained token, limited to that one repository, with read-only access to Contents. Nothing more. Do not create a classic token with broad repo scope; it grants far more than this connector uses.
- On GitHub, open your account Settings → Developer settings → Personal access tokens → Fine-grained tokens. At the time of writing this is github.com/settings/personal-access-tokens.
- Generate new token. Give it a name you will recognise later and an expiry date you are willing to renew.
- Under Resource owner, choose the account or organisation that owns the repository.
- Under Repository access, choose Only select repositories and pick the one.
- Under Repository permissions, set Contents to Read-only. Leave everything else at No access. (Metadata is usually switched on automatically as a prerequisite; that is expected.)
- Generate the token and copy it — it is shown once.
- In Clause50, choose the GitHub type, supply the token as the GitHub personal access token, and give the Repository as
owner/name— for exampleacme-inc/checkout-service, not a full web address.
If the layout has changed: look for “fine-grained” tokens under developer settings, then for a permission named Contents at read level. If the repository belongs to an organisation, that organisation may have to allow fine-grained tokens, and your request may sit pending approval by one of its owners — in which case the token exists but cannot yet read the repository.
You find out immediately if you got it wrong. The moment you add the connector, Clause50 makes one live authenticated call to GitHub for that repository with that token. A wrong token, a typo in the repository name, a repository you cannot see, or a permission that is too narrow all fail there and then, rather than silently becoming a failed sync hours later. OpenAI and Anthropic keys are not checked at this point — for those, the first sync is where a bad key surfaces, so press Sync now after adding one.
What each connector actually collects
Worth reading before you rely on a connector to close a gap: the scope is narrower than people expect, and the narrowness is intentional.
- OpenAI and Anthropic — usage totals onlyOne usage record per day: the period covered, the models used, the token totals, and — for OpenAI only — a request count. That is all of it. These connectors never record interaction samples, the kind of evidence that represents actual conversations.
- GitHub — commit referencesOne record per new commit, carrying the commit's identifier and the repository name. Not the changes themselves, not file contents, not commit messages.
- Manual — whatever you importAny of the seven kinds of evidence, exactly as your file states them. See the format →
Why the usage connectors stop where they do. The vendor reports they read return totals, not conversation content. Clause50 could have labelled those totals as interaction samples and let them satisfy the transparency checks that look for evidence of disclosure. It deliberately does not. Doing so would let a system read as compliant on the strength of data that never touched a real conversation — the check would pass, the record would look complete, and the underlying duty would be entirely unproved. Clause50 does not manufacture an observation it did not make, so the connector records what the report honestly returned, and nothing more.
The practical consequence, stated so it is not a surprise: connecting OpenAI or Anthropic does not by itself move your Article 50 score. It gives you a continuous, tamper-evident record of operational activity, which is real evidence and appears in your documents. Duties that need proof of what a user was shown are met by a statement or an uploaded document today. See Evidence.
Manual import — the file format
The Manual type takes no credentials of any kind. You add the connector first, and a bulk import box then appears beneath it. That box does not exist until a manual connector exists on that system — if you are looking for somewhere to upload your file and cannot find it, this is why.
It accepts a CSV (a spreadsheet saved as comma-separated values) or JSON (a structured text format). Give a CSV file a .csv extension; anything else is read as JSON. Each row becomes one piece of evidence. The columns are:
kind— requiredOne oftrace_batch,usage_stat,eval_result,commit_ref,doc_upload,attestation,config_snapshot. Anything else fails validation.payload— optionalThe record itself, as a JSON object. In a CSV this is one cell holding that object, which usually means quoting the cell and doubling any quotes inside it, per ordinary CSV rules.periodStart/periodEnd— optionalTimestamps in ISO 8601 form — the international standard, written2026-06-01T00:00:00Z— for evidence covering a window of time rather than an instant.
A minimal JSON file therefore looks like this:
Three behaviours to know before you import anything:
- 1000 rows maximum per importSplit a larger file. The cap is what keeps a single import inside its time budget.
- One bad row rejects the whole batch, and nothing is importedEvery row is validated before a single one is written. If row 847 has a misspelled kind, rows 1 to 846 are not imported either. This is the safe behaviour: a half-imported file leaves you unable to tell what made it in, on a record that cannot be edited afterwards to sort it out.
- Re-importing the same file appends the rows againThere is no duplicate detection on manual import — import the same spreadsheet twice and every row appears twice. Deliberate: for a record that can only be added to, duplicates are the safe failure and lost evidence is not. The alternative would mean deciding that two rows are “the same” and silently discarding one, and a rule that silently discards evidence is worse than a record that visibly contains a duplicate.
Syncing
Sync now runs one connector immediately: Clause50 unseals the stored credential, calls the provider, records any new evidence it finds, and notes the outcome. It is not offered for a manual connector, which is not polled — use the bulk import instead.
On a schedule. Connectors also sync automatically every hour. Nothing has to be running on your side and you do not need to keep pressing the button. A scheduled pass takes connectors oldest-first so none is starved, and one connector failing never stops the others.
What you see afterwards, in the connector list:
- Status active, a fresh last-sync time, no errorThe sync ran. Note that zero new evidence is a perfectly normal result — a repository with no new commits, or an OpenAI organisation with no usage in the window, produces nothing, and inventing an empty record would be worse than producing none.
- Status error, with a messageThe sync failed — most often a rejected key. Its place in the provider's history is left untouched, so once the cause is fixed the next sync resumes exactly where the last good one stopped and nothing is skipped. The message is deliberately short and never includes your credential or the provider's raw response.
Rate limits are not failures. Providers cap how often they can be asked for data. If GitHub signals that your token is running low on its allowance, the connector stops cleanly, keeps the commits it already processed, stays active, and resumes on the next pass. You will not see an error for this, because there is nothing for you to fix.
One detail specific to GitHub. The connector remembers the most recent commit it has seen and asks only for commits after that point — but with a deliberate five-minute overlap, plus a list of recently seen commits so the overlap does not produce duplicates. The overlap exists because commit dates are not strictly ordered by when they were published: a commit can arrive carrying a timestamp already behind the marker, and without the overlap it would be skipped forever. Skipping a commit is a real gap in the record; briefly re-examining a few is not.
Removing a connector
Remove deletes the connector and its stored credential. It does not delete the evidence that connector already contributed — that record can only be added to, and stays exactly where it is, which is the point. Removing a connector stops future collection; it does not rewrite history.