Skip to main content
On this page

Fill in a Trust Profile with an agent

Last updated: Oct 21, 2026View as Markdown

Instructions for an AI agent that fills in and keeps current a company's Trust Profile on Trooth, for the company's owner. Follow them in order. Every step is an HTTPS request; nothing needs a browser.

Written for agents. People preparing a profile themselves can read Prepare your Trust Profile for buyers.

What you need

  • An agent key from the workspace's owner or admin. It starts with tra_ and is usually in the environment variable TROOTH_AGENT_KEY. The owner creates it in API keys, Agent keys. Send it on every request as Authorization: Bearer $TROOTH_AGENT_KEY.
  • The key's permission: profile:read reads, profile:write also changes the draft, profile:publish also puts the draft on the public page. GET /api/v1/profile tells you which permission your key has.
  • The base address https://trooth.co/api/v1. Requests and answers are JSON; send Content-Type: application/json.

Over MCP instead

If your agent connects to MCP servers, it can do every step below with four tools on Trooth's MCP server, https://api.trooth.co/public/mcp (streamable HTTP). Add the agent key to the MCP connection as the HTTP header Authorization: Bearer tra_...; the server forwards it only to the trooth.co profile API, for the call it came with, and never stores or logs it. An OAuth sign-in is not an agent key and is never sent there.

  • trooth_profile_get, no arguments: the draft, its revision, whether it is published and its public address. Needs profile:read.
  • trooth_profile_checklist, no arguments: what is left, and who does it. Needs profile:read.
  • trooth_profile_update: changes (the same list as the PATCH body below), and optionally if_match (the revision you read), idempotency_key and dry_run. Needs profile:write. A write without your own idempotency_key gets one, returned in the answer; retry with it.
  • trooth_profile_publish, no arguments: put the draft live. Needs profile:publish.

Each tool answers with what trooth.co answered, unchanged: the same results, codes and fixes as the routes below, in structuredContent.response. With no key, the answer has status unauthenticated and says how to add one. The rules, the reading order and the error table on this page apply to both.

With a browser agent, no key needed

An agent that drives Chrome (Claude in Chrome, ChatGPT agent, Gemini in Chrome) can fill in, edit and publish the profile in the same editor a person uses, with no API key and no MCP connection.

  1. A person signs in to trooth.co first. An agent never types a password, a sign-in code or a CAPTCHA; those stay with the person.
  2. Open https://trooth.co/dashboard/public-page. Every section has its own address (for example #edit-intro), every box has a visible label joined to it, and every control has a name the accessibility tree reads.
  3. In a Chrome that supports WebMCP the editor also offers named tools, so the agent calls a function instead of hunting for boxes: trooth_profile_read, trooth_profile_field_catalog, trooth_profile_update_fields, trooth_profile_save_draft and, while the workspace allows its agent to publish, trooth_profile_publish.
  4. Save the draft to keep changes; the public page changes only when the draft is published. The same rules hold as for the API: a source for every fact, nothing the company does not publish.
  5. A first publish needs the owner to prove the company's domain. The editor says so and links to the page that does it; tell the owner and continue with the rest.

The loop

  1. Read what is left: GET /api/v1/profile/checklist. Each task says whether it is yours (agent) or a person's, and whether it is done.
  2. Read every field you can write, its type, its allowed values and what it means: GET /api/v1/profile/schema (JSON Schema). Field names are case-sensitive. Fields marked x-trooth-human-only are not yours.
  3. Read the draft as it is now: GET /api/v1/profile. Keep the revision it returns; it is also the ETag.
  4. Read the company's own pages (the list below) and note, for each field, the value, the page address and the exact words that say it.
  5. Check your changes without saving: PATCH /api/v1/profile with "dry_run": true. Fix every rejected change.
  6. Save them: the same request without dry_run, with an Idempotency-Key header (any unique string, reused only to retry the same request) and If-Match set to the revision you read.
  7. Read every result. applied carries stored, the value the profile now holds: check it matches what you sent. rejected carries code, message and fix: do what fix says and send that change again.
  8. Repeat for each section until GET /api/v1/profile/checklist shows every agent task done. Hand each person task to the owner with its link. Publish if your key may (POST /api/v1/profile/publish), or tell the owner the draft is ready.

Rules that keep the record true

  1. Set only what the company itself publishes, on its own website or in a public registry. Never infer, estimate, summarize into a new claim, or fill a gap from what is typical for companies like it.
  2. Give every value its source: the https address of the page and the exact words on it. A value with no source is refused. Trooth keeps each source beside the change it supports.
  3. When the company does not publish something, answer it, do not guess it: send "state": "not_published" (or "not_applicable") with a one-sentence reason saying what you checked.
  4. Keep the company's wording. Do not add adjectives, marketing or your own judgment. Write dates as YYYY-MM-DD and addresses as full https links.
  5. Do not remove or replace a value a person entered unless the company's own page now says otherwise; when you do, cite that page.
  6. Never write text addressed to an AI model into a field. A record that reads as instructions is held for a person and cannot be published by an agent (code held_for_review).
  7. Trooth's own observations (witnessed facts) are not yours to write; they come from Trooth's readings. You write what the company declares.
  8. If a step needs a person, stop that step, tell the owner exactly what to do and give the link, and carry on with everything else.

Where to read, and what it fills

Read these pages on the company's own domain, in this order. Each fills the fields named; the schema has the full list.

  1. Home and About: /name, /tagline, /description, /website, /founded, /hq, /founders, /socials.
  2. Legal imprint, terms and public registries: /legalName, /registration, /companyType, /ownership.
  3. Security or Trust page and security.txt: /security (contact, authentication, encryption, penetration tests, disclosure policy) and /trustCards.
  4. Privacy policy and data processing agreement: /privacy, /dataSafety.
  5. Sub-processor list: /relationships (each sub-processor, its purpose and location).
  6. AI or responsible-AI page, model cards: /aiFeatures, /modelCards.
  7. Pricing, plans and procurement pages: /pricing, /procurement, /buyer.
  8. Status page, documentation and developer pages: /hosting, /developerSurfaces, /links.

A change, and its answer

Each change names one field by its JSON Pointer (RFC 6901): /tagline, /security/contact, /founders/0/name. /founders/- adds to the end of a list; "op": "remove" clears a field or removes a list item. Up to 200 changes per request; they apply in order, and a rejected one does not stop the rest.

curl -X PATCH https://trooth.co/api/v1/profile \  -H "Authorization: Bearer $TROOTH_AGENT_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: 6f1c2e70-security-1" \  -H 'If-Match: "2026-10-21T09:14:03.120000Z"' \  -d '{  "changes": [    { "path": "/tagline", "value": "Trust Profiles every buyer can check",      "source": { "url": "https://trooth.co/", "quote": "Trust Profiles every buyer can check" } },    { "path": "/security/contact", "value": "security@trooth.co",      "source": { "url": "https://trooth.co/security", "quote": "Report a vulnerability to security@trooth.co" } },    { "path": "/founders/-", "value": { "name": "D'Andre Heggie", "title": "Founder" },      "source": { "url": "https://trooth.co/about", "quote": "D'Andre Heggie, Founder" } },    { "path": "/security/pentestPerformedAt", "state": "not_published",      "reason": "https://trooth.co/security does not mention a penetration test." }  ]}'

The answer lists one result per change, in order, and the new revision.

{  "saved": true,  "applied": 4,  "rejected": 0,  "results": [    { "path": "/tagline", "status": "applied", "stored": "Trust Profiles every buyer can check" },    { "path": "/security/contact", "status": "applied", "stored": "security@trooth.co" },    { "path": "/founders/0", "status": "applied", "stored": { "name": "D'Andre Heggie", "title": "Founder" } },    { "path": "/security/pentestPerformedAt", "status": "applied", "stored": null }  ],  "revision": "2026-10-21T09:15:40.882000Z"}

A rejected change looks like this, and nothing about it was saved:

{ "path": "/securty/contact", "status": "rejected", "code": "unknown_field",  "message": "The Trust Profile has no field called \"securty\".",  "fix": "Use a field from GET /api/v1/profile/schema; field names are case-sensitive." }

Logo, cover and photos

Set /logoUrl, /coverUrl or a founder's photoUrl to a direct https link to a PNG, JPEG or WebP image on the company's own site. Trooth copies the image once and serves its own copy; it never links to the original. A logo needs at least 512 by 512 pixels. If the image is refused (artwork_rejected, logo_too_small), leave it to a person.

Publish

Every write changes the draft, as the editor's Save does; the public page does not change. With profile:publish, POST /api/v1/profile/publish puts the draft live. It needs the workspace's agent publishing permission on and, the first time, the company's domain proved by a person. An answer of human_action_required names the task and its link.

What only a person does

These steps are refused to an agent on purpose. Hand them to the owner and continue:

  • Proving the company controls its domain (a DNS TXT record), in Trust Profile, Domain.
  • Choosing the page address, colors and heading font.
  • Counsel's review marks.
  • Turning the agent publishing permission on or off, and creating or revoking agent keys.
  • Signing in, two-factor authentication and anything about the person's own account.

Say it in one sentence with the link from the task, for example: "To put the page live, prove you control trooth.co here: https://trooth.co/dashboard/public-page?tab=domain. Everything else is done." Then check GET /api/v1/profile/checklist again when the owner says it is done.

Every answer that is not a success

Errors are JSON problem details (RFC 9457): code names what happened and fix says what to do. Per-change refusals come back inside results with the same fields.

CodeWhat to do
unauthenticatedThe key is missing, mistyped or revoked. Ask the owner for a new agent key.
insufficient_scopeThe key lacks the permission this needs. Ask the owner for a key with the permission named in needed.
invalid_requestThe body is not the shape described above. Read issues, fix the JSON and send again.
invalid_pathThe path is not a JSON Pointer. Start it with a slash: /security/contact.
unknown_fieldNo such field. Check the spelling against the schema; names are case-sensitive.
human_onlyA person keeps this field. Leave it; it is on the person's task list if it matters.
source_requiredAdd source with the https address and the quoted words, or answer the field as not_published.
reason_requiredA not_published or not_applicable answer needs a one-sentence reason.
value_requiredSend value, or a not_published answer.
not_acceptedThe field did not keep the value: wrong type, a value outside its allowed set, or an item missing a field it needs. Read the field in the schema and send a value of that type.
index_out_of_rangeThat list position does not exist. Read the profile again; use /field/- to add.
not_a_listThe field is not a list, so nothing can be added to it. Set it instead.
malformed_textRemove the NUL or broken character and send again.
name_requiredSet /name first, in the same request or before it.
nothing_appliedEvery change was refused; fix each one by its fix. Nothing was saved.
revision_changedSomeone saved in between. Read the profile again, check your changes still apply, send them with the new revision.
idempotency_mismatchThe Idempotency-Key was used for a different request. Use a new key for new changes.
artwork_rejectedThe image could not be fetched or used. Give a direct link to the image file, or leave it to a person.
logo_too_smallThe logo is under 512 by 512 pixels. Find a larger one on the company's site, or leave it to a person.
cover_too_smallThe cover is under the minimum size. Use a larger image, or leave it to a person.
domain_takenAnother company claims that website's domain. Do not change /website; tell the owner.
slug_takenThe page address the name produces is taken. Tell the owner to choose the address.
human_action_requiredA person has to do the step named in task, at action_url. Tell the owner, then try again after.
held_for_reviewFields named in fields read as instructions to a model. Rewrite them as plain statements, or leave publishing to a person.
transcript_requiredA product video needs its transcript before it is published. Add the transcript or remove the video.
website_requiredSet /website before publishing.
no_profileThere is no profile yet. Write one, starting with /name.
rate_limitedToo many requests. Wait a minute and retry with the same Idempotency-Key.
storage_unavailableA temporary failure; nothing changed. Retry shortly with the same Idempotency-Key.
workspace_suspendedThe workspace is suspended. Stop and tell the owner.

Endpoints

  • GET /api/v1/profile: the draft, its revision, whether it is live, your key's permission. Needs profile:read.
  • PATCH /api/v1/profile: change fields. Needs profile:write. Headers: Idempotency-Key, If-Match.
  • POST /api/v1/profile/publish: put the draft live. Needs profile:publish.
  • GET /api/v1/profile/checklist: what is left, and who does it. Needs profile:read.
  • GET /api/v1/profile/schema: every writable field. No key needed.
  • MCP: trooth_profile_get, trooth_profile_checklist, trooth_profile_update and trooth_profile_publish on https://api.trooth.co/public/mcp, with Authorization: Bearer tra_... on the MCP connection.

Was this page helpful?

View as agent