Cleanrooms: start here

A cleanroom lets an owner share access to analysis of protected data. Members can ask questions and receive approved reports without downloading the owner's source files.

Use the portal for the walkthrough below. If you are connecting an agent or writing an integration, the complete agent guide contains signup, authentication, funding, every API, and MCP tool instructions. Its plain Markdown version needs no JavaScript or sign-in.

Sign up and sign in

  1. Open Sign up, enter your email and password, and verify the code sent to your inbox.
  2. Review and accept the Terms. Account setup records your acceptance before opening the portal.
  3. Use the same verified email that a room owner granted access to. Existing accounts receive access immediately; a grant made before signup attaches when that email is verified and the account is created.

If setup fails after sign-in, use Retry setup. Do not create a second identity to work around a setup error. An agent signing up independently needs access to its own inbox to retrieve the confirmation code.

Create or open a room

Open Cleanrooms in the portal. Owners create a room with a title, then add source files and grant access to members. Members open an accessible room from Your rooms or an emailed room link. A link may prompt you to sign in; opening it does not itself grant access unless the owner lets anyone with the link join, in which case you can click Join room.

The owner controls source files, membership, question approval, and report release. Members submit analysis requests and see their own run history and released reports. Membership alone does not permit reading or downloading source data.

Invite someone to supply the data

You can initiate a room even when someone else owns the data. In Create room, choose Invite data owner, enter a title and the owner's email, and send the invitation. The room waits for its owner to accept. Copy its direct invitation link to send it yourself if needed; the same room and link continue working after acceptance.

The recipient signs in or creates an account with the invited, verified email. The invitation link opens the pending room, where they review who requested it and accept ownership. They become the owner and can upload files; the requester becomes a member. The requester cannot browse or download those files. The owner controls membership and approves analysis requests and report release as usual.

Delete a room

An owner can permanently delete a room from the bottom of the room page by typing the room title to confirm. Deletion cuts all member access immediately, cancels and refunds runs still in progress, and then wipes every version of the room's files, its title and purpose, member emails, and all run requests and reports. A report already released to a member stays readable by that member. Deletion cannot be undone. The room page shows Deleting… while the wipe runs and Deleted once it completes; the owner's GET /api/v1/clean-rooms/{id} reports the same progress in deletion. Wiped data can remain in encrypted database backups for up to 35 days before those backups expire.

Deleted data can also remain in application logs for up to 90 days. IDs of the room, its runs, members and files, file hashes and sizes, receipts, and file names reduced to hashes are kept as the audit and billing record. File contents are not kept. Amnetic never trains AI models on your data.

Continue with Files, Members, Funding, Analysis, or Agent connections.

Files

There are two separate file scopes:

Files Who controls them What they are for
Room source files Room owner Protected data used in the room's analysis
Your supporting files Your account Briefs, examples, code, and documents you choose for a request

Amnetic does not use your files, requests, or reports to train AI models. See the Privacy Policy.

Room source files

As an owner, open a room's Files card to add, replace, or remove a file. A successful write means the file is ready for future runs. A failed replacement keeps the previous file. Members cannot download the owner's source files.

To add a whole folder with its subfolders, use Upload folder or drop it onto the card.

Supporting files

Choose only the personal files relevant to your analysis request. Files remain private to your account until you select them for a run; selecting a file supplies that version to the room's evaluator. The owner's question review includes the file's name, size, and checksum, not a download of its contents. Do not attach a document you are unwilling to share for that review.

Paths look like /research/brief.md. Folders are derived from file paths; there is no separate folder creation step. Paths are case-sensitive. Traversal (..), backslashes, control characters, and empty path segments are rejected.

Personal files must be nonempty, pass scanning, and be at most 25 MiB each. A run can select at most 20 files, totaling 100 MiB. Uploading a document does not mean its full text is automatically inserted into the model prompt.

Frozen inputs

Starting a run freezes both the selected supporting-file versions and the room source snapshot. Replacing or deleting a file later affects future runs; it does not change the inputs of a run already started.

Deleting or replacing a supporting file permanently destroys the earlier version once no run uses it. A version a run used is kept with that run until the run's records are wiped: when the run's retention policy is due or its room is deleted (not for a report released to you as a member), or when your account is closed. Files you keep do not expire.

The evaluator receives selected supporting files read-only under /inputs, preserving their paths. Unselected personal files are absent. Protected room source data remains separate.

For file operations and exact limits, see the agent guide.

Members

The owner grants access by email from the room's Members card. Click Invite, enter the email in the new row, and submit it.

  • Existing verified account: access is granted immediately.
  • Pending: that email does not have an associated account yet. The grant attaches automatically when the recipient signs up with the verified email.
  • Remove: revokes access to future room operations and runs.

An owner's invitation to a member has no acceptance step. A notification email links to the room; delivery status is separate from access. A delayed or failed email does not undo an access grant.

Anyone with the link

The owner can turn on Anyone with the link can join in the Members card and copy the room link. Anyone signed in who opens the link can click Join room and becomes a member, the same as if invited. As with any member, the owner sees their email. Rooms are never listed or searchable. Turning it off stops new joins; existing members stay. A removed member cannot rejoin through the link.

Only the owner manages membership. Members do not receive the roster or other members' identities. Always check the email before granting access.

An owner reviews a member's question before work starts and reviews its report before release. These approvals are explained in Analysis.

Requests sent to a data owner

If someone else initiates the room and invites you to own it, sign in with the invited email and open the room's invitation link, and review who initiated it. The room is awaiting your acceptance; you cannot upload files or run analysis yet. Accepting opens that same room under your ownership and admits the requester as a member. Its ID and link stay the same. They receive analysis access, with your approval of each request and report, and cannot view your source files. You can remove their membership using the same controls as any other member.

Funding

A member needs enough account credits for the quoted run reservation. Open Account → Billing & credits, select Add credits, choose the amount, and complete the payment. Return to the portal and confirm the credit balance before submitting a run. A payment redirect or receipt alone is not proof that credits have arrived.

What a run costs

The room's run quote states the machine size, maximum runtime, fixed fee, reservation, and price-schedule version. Review the quote before confirming. If the quote changes, request and approve the new price rather than retrying an old price blindly.

Credits reserved for a run are unavailable to spend on a second run. The balance already excludes reserved funds; do not subtract the reservation again. Purchased credits are for usage and are not withdrawable cash.

Independent agents

The agent guide describes programmatic MPP funding. An independent agent needs an authorized payment instrument or funded wallet. Stripe's merchant configuration and payment-method availability determine which methods can complete payment. A method that asks for human approval is not an unattended payment path.

MPP funding is not ready to rely on until merchant configuration and a real payment roundtrip have been verified. Human browser checkout remains the established payment path during that verification.

For payment failures, check the account balance and funding status before starting a new payment. Reuse the funding request's idempotency key when retrying the same amount.

Analysis

Open a room you have access to and write the analysis you want. Include the goal, background, constraints, desired output, and examples. Select supporting files from your account if needed.

Submit a request

  1. Review the run price, machine size, and runtime.
  2. Confirm the request and selected files. The run freezes these inputs.
  3. Follow the run status in the room. The owner must approve the question before work starts.
  4. When a report is ready, wait for the owner to approve its release.
  5. Read the released report in the run. A completed analysis is not available to the member until released.

A member sees their own runs. The owner sees the pending decisions needed to approve questions and release reports. An owner may decline a question or report; read the message on the run rather than submitting identical requests repeatedly.

Decisions are made in the portal. An owner can let one of their API keys make these decisions by allowing it under API keys in the portal. Keys cannot decide until the owner allows it, and a CLI login (amnetic login) cannot decide or allow a key.

Large requests

The revised run API accepts request text up to 512 KiB of UTF-8. This is a byte limit, not a guaranteed token budget. Transport through the evaluator and released-report flow has been verified with a provider-counted 64,096-token request using scripted model decisions. A live model analysis at that size has not yet been verified; split or reduce requests if the selected model cannot process all inputs. Source files, instructions, and output also consume the model's capacity. Inputs must never be silently truncated.

Troubleshooting

  • Sign-in expired: sign in again, then reopen the room.
  • Room unavailable: confirm the account uses the granted verified email and that the owner has not revoked access or closed the room.
  • Insufficient credits: check the available balance and outstanding reservations, then fund the account.
  • Price changed: obtain a fresh quote and confirm it.
  • Waiting for approval: the owner must act; repeated polling does not approve the request.
  • Failed or expired run: inspect its failure code and message before retrying. Starting another run creates a new request and can reserve credits again.

See the agent guide for exact API fields, decision hashes, states, and retry rules.

Agent connections

Open Agents in the portal to manage MCP connections, plugins, and API keys for your cleanroom account. The complete connection and coding instructions are on the agent guide.

MCP

The MCP endpoint is https://market.amnetic.ai/mcp. Clients supporting browser authorization can connect and sign in. An independent agent can use a personal account API key as a bearer credential after completing verified signup and Terms acceptance.

API keys

Create a key for the integration, copy its secret once, and store it in the agent's credential store. The secret is not returned again by the key list. Revoke a key when it is no longer needed. Do not put credentials in source files, screenshots, prompts, or shared analysis briefs.

An API key carries your account's authority. It does not bypass room membership or permit reading another account's files. Use ordinary account keys for this guide; narrowly scoped runtime credentials have a separate purpose and do not provide account onboarding authority.

For Hermes, OpenClaw, and other agents, provide the single Markdown guide. The agent still needs an inbox for signup and a payment instrument for funding.

Amnetic cleanrooms: complete agent guide

Use this page to create an account, authenticate, manage files and room access, fund usage, request analysis, and retrieve a released report. It is also available verbatim as plain Markdown. Humans can follow the portal walkthrough.

Availability

Programmatic MPP funding still requires merchant configuration and a real payment roundtrip. Selected supporting files mount read-only under /inputs in the evaluator. A 512,266-byte request counted as 64,096 tokens by the configured provider passed the input transport and released-report flow in the hosted lab using scripted model decisions. This proves transport, not a live model analysis or a guaranteed token budget; the request limit remains 512 KiB of UTF-8.

Do not treat a successful upload as proof that every byte will fit in a model's prompt. Selected personal files mount read-only; protected room source data is accessed separately through authorized tools. The owner question review receives their metadata (filename, size, and hash), not a personal-file byte download. Never silently truncate an analysis brief.

Addresses and identity

Setting Production value
Website and portal https://amnetic.ai, https://amnetic.ai/portal.html
REST origin https://market.amnetic.ai
MCP endpoint https://market.amnetic.ai/mcp
Cognito API https://cognito-idp.us-west-2.amazonaws.com/
AWS region us-west-2
Cognito public app client ID 4a0rroko7aumoehtl85k6vt9rv
Cognito user pool us-west-2_BAlMlYQS1
Cognito hosted sign-in https://amnetic-prod.auth.us-west-2.amazoncognito.com

The Cognito client has no client secret. These public identifiers come from the website's production configuration. Signup does not require AWS access keys.

Use Authorization: Bearer <Cognito IdToken> on REST requests until an account API key has been created. Use the ID token, not Cognito's access token, for these requests. Identity is derived from verified credentials; never submit an account ID or email to choose which account a request operates on. Account files, credits, and keys are scoped to that credential. An API key does not bypass room membership.

Signup

You need an email inbox you can read and a password with at least eight characters, including uppercase, lowercase, a number, and a symbol. Email confirmation remains required for agents. A wallet is not a substitute for verified identity.

Cognito operations are HTTPS POSTs with Content-Type: application/x-amz-json-1.1 and the operation-specific X-Amz-Target below. These calls use the public client ID and no Amnetic authorization header.

Create and confirm the identity

POST https://cognito-idp.us-west-2.amazonaws.com/
Content-Type: application/x-amz-json-1.1
X-Amz-Target: AWSCognitoIdentityProviderService.SignUp

{"ClientId":"4a0rroko7aumoehtl85k6vt9rv","Username":"agent@example.com","Password":"YOUR_STRONG_PASSWORD","UserAttributes":[{"Name":"email","Value":"agent@example.com"}]}

The response contains UserSub, UserConfirmed, and confirmation delivery details. Read the email code, then:

POST https://cognito-idp.us-west-2.amazonaws.com/
Content-Type: application/x-amz-json-1.1
X-Amz-Target: AWSCognitoIdentityProviderService.ConfirmSignUp

{"ClientId":"4a0rroko7aumoehtl85k6vt9rv","Username":"agent@example.com","ConfirmationCode":"CODE_FROM_EMAIL"}

An empty success response confirms signup. To request another code, use AWSCognitoIdentityProviderService.ResendConfirmationCode with {"ClientId":"4a0rroko7aumoehtl85k6vt9rv","Username":"agent@example.com"}. Do not log passwords or confirmation codes.

Authenticate and renew

POST https://cognito-idp.us-west-2.amazonaws.com/
Content-Type: application/x-amz-json-1.1
X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth

{"AuthFlow":"USER_PASSWORD_AUTH","ClientId":"4a0rroko7aumoehtl85k6vt9rv","AuthParameters":{"USERNAME":"agent@example.com","PASSWORD":"YOUR_STRONG_PASSWORD"}}

On success, AuthenticationResult contains IdToken, AccessToken, RefreshToken, ExpiresIn, and TokenType. If Cognito returns a challenge instead, complete that challenge before calling Amnetic. Renew with the same operation and {"AuthFlow":"REFRESH_TOKEN_AUTH","ClientId":"4a0rroko7aumoehtl85k6vt9rv","AuthParameters":{"REFRESH_TOKEN":"YOUR_REFRESH_TOKEN"}}. Store tokens in a credential store.

Provision the account and accept Terms

POST /api/v1/accounts
Authorization: Bearer YOUR_ID_TOKEN
Content-Type: application/json

{"name":"Research agent","tos_version":"2026-10-13"}

201 means a new account; 200 means it already exists. name is optional. tos_version is the provisioning field; it does not replace server-recorded Terms acceptance. The account response includes its account representation and a server-selected portal navigation projection, not a feature catalogue.

  1. GET /api/v1/account/tos-status returns current_version, accepted, and instrument_url (and acceptance timestamp when applicable).
  2. Read the Terms at instrument_url. Only proceed with the account operator's authorization to accept them.
  3. POST /api/v1/account/tos-acceptances with {"expected_version":"VERSION_FROM_STATUS"} records acceptance. 201 is new acceptance; 200 is an existing acceptance. 412 tos_version_changed means reread the current instrument before accepting again.

Provisioning attaches any active access grants addressed to this identity's verified email. There is no invitation token to exchange or acceptance API to call.

Create an account API key

POST /api/v1/accounts/api-keys with {"name":"hermes-cleanrooms"} returns 201 and {"id":"KEY_ID","plaintext":"SECRET","prefix":"PREFIX","name":"hermes-cleanrooms"}. Save plaintext once; it is not returned again. Use Authorization: Bearer SECRET for supported account REST and MCP operations. List keys with GET /api/v1/accounts/api-keys ({"keys":[...]}); revoke with DELETE /api/v1/accounts/api-keys/KEY_ID.

Use an ordinary account key, not a scoped evaluator credential. Bootstrap and accepting Terms can always be completed with a fresh Cognito ID token. Never supply credentials inside an analysis request or file.

REST contract

All paths below are relative to https://market.amnetic.ai. Authenticated requests require the bearer credential described above. Send Content-Type: application/json for JSON bodies, or a file's actual media type for raw file writes. UUIDs and timestamps are strings; JSON numbers representing money are integers unless explicitly formatted otherwise. Do not mix cents, microdollars, and decimal USD.

Rooms and access

Method and path Input Output and authority
POST /api/v1/clean-rooms {"title":"Research room"} Created room; caller owns it
GET /api/v1/clean-rooms None Accessible owner/member room projections
GET /api/v1/clean-rooms/{id} None Role-specific room projection; source metadata and roster only for owner
POST /api/v1/clean-rooms/{id}/close None Close own room to future work
DELETE /api/v1/clean-rooms/{id} {"confirm_title":"..."} Owner permanently wipes the room (202); signed-in session only
POST /api/v1/clean-rooms/{id}/members {"email":"member@example.com"} Owner grants access; existing verified account active, otherwise pending
DELETE /api/v1/clean-rooms/{id}/members/{grant_id} None Owner revokes that grant
PUT /api/v1/clean-rooms/{id}/open-join {"enabled":true} or {"enabled":false} Owner lets anyone signed in who has the room link join, or makes the room invite-only (the default)
POST /api/v1/clean-rooms/{id}/join None Join a room whose owner allows link joining; returns the member projection. Repeating it, or joining a room you already belong to, returns the room unchanged

Room creation/detail returns an object shaped as {"room":{"id":"ROOM_ID","title":"Research room","status":"open","opened_at":"TIMESTAMP"},"role":"owner","member_count":0,"data":{},"access_grants":[]}. The role-specific data projection carries metadata, never member-readable source bytes. Listing wraps projections in {"data":[...]}. A grant returns 201 with id, room_id, email, optional member_id, state, and created_at; use its id in revocation. Close and revoke return updated room projections.

Keep the returned room ID and access grant ID. A room projection includes its role, title, status, and member count where permitted. Owner detail includes access grants and notification delivery information. A notification email opens the room and prompts sign-in as needed; receiving or opening it does not confer authority. Pending means the account has not been associated yet, not awaiting invitation acceptance.

Rooms are never listed or searchable. When link joining is on, the room projection's room.open_join_enabled_at is a timestamp and anyone signed in who has the room ID can join; a joined member is an ordinary member, whose email the owner sees, with an access grant the owner can revoke. A revoked member cannot rejoin through the link; the owner must grant access again. Every refused join, including an invite-only, closed, or deleted room, is 404.

An owner controls data and approval decisions. A member can request analysis and read its own released reports, not the owner's files or other members' identities. Being an owner does not imply a separate member account is provisioned for run submission.

Files

Paths are absolute within their scope, case-sensitive, and use forward slashes, for example /research/brief.md. URL-encode each path segment when constructing REST URLs; keep / as the separator. The root listing path is /. No separate folder objects are needed: folder entries are derived from stored file paths. Reject .., backslashes, control characters, duplicate slashes, and empty file paths.

Operation Personal scope Room scope
List folder GET /api/v1/files?path=/research GET /api/v1/clean-rooms/{id}/files?path=/
Read file GET /api/v1/files/research/brief.md GET /api/v1/clean-rooms/{id}/files/source/data.csv
Add/replace PUT /api/v1/files/research/brief.md PUT /api/v1/clean-rooms/{id}/files/source/data.csv
Remove DELETE /api/v1/files/research/brief.md DELETE /api/v1/clean-rooms/{id}/files/source/data.csv

Listing returns {"entries":[{"path":"/research/brief.md","type":"file","size_bytes":123,"updated_at":"2026-10-01T12:00:00Z"}]}. type is file or directory. PUT sends raw file bytes, not multipart or JSON; a successful 200 returns file metadata after scanning/preparation. GET returns raw bytes with their content type. DELETE returns 204. A failed replacement preserves the prior file.

Personal files are nonempty and limited to 25 MiB each. A run can select up to 20 personal files totaling 100 MiB. Room writes use the owner-only scanned preparation pipeline; members cannot list or read owner source bytes. Room MCP inline transfers retain smaller limits than REST; see the tool table.

A run selects personal paths through files, not attachment IDs. Those paths resolve to immutable file versions when the run is admitted. Replacing or deleting their current heads later cannot change the run. A deleted or replaced version is destroyed once no run references it, and a version a run used is destroyed when that run's records are wiped: when the run's retention policy is due or its room is deleted (not for a report released to you as a member), or when your account is closed. Amnetic does not use your files, requests, or reports to train AI models. Room source inputs are also frozen. Only the selected personal-file versions are supplied to the evaluator. The owner question review includes their frozen metadata, not a personal-file byte download; the rest of the account filesystem remains private.

There is no public evaluation-attachments API in this contract. The evaluator mounts only explicitly selected, frozen supporting files read-only, with /research/brief.md becoming /inputs/research/brief.md. The files and parent directories prevent modification, deletion, or permission changes by the evaluator. Unselected account files are absent. Protected room source data retains its separate access boundary.

Funding

GET /api/v1/accounts/credits returns balance_cents, evaluation_reserved_micro, withdrawable_balance_cents, and recent_entries. The spendable balance already excludes reservations. balance_cents is integer USD cents; evaluation_reserved_micro and run quote expected_charge use integer micro-USD (1 USD = 1,000,000 micro-USD). Purchased credits are spend-only, not withdrawable funds.

Human browser checkout remains available through POST /api/v1/accounts/credits/topup with {"amount_cents":2500}. It returns checkout_url and session_id; confirmed payment credits the account asynchronously. Do not infer crediting from opening or returning from checkout.

Machine payments

Funding amount bounds default to 500–100,000 cents ($5–$1,000), with the server authoritative. A funding idempotency key is nonempty and at most 128 characters.

MPP requires a configured merchant and an authorized payment client. A funded wallet can permit unattended payment; a card route requiring human approval cannot. Merchant/payment-method availability must be verified before relying on machine funding in production.

POST /api/v1/account/funding
Authorization: Bearer ACCOUNT_CREDENTIAL
Idempotency-Key: ONE_UNIQUE_KEY_FOR_THIS_FUNDING_REQUEST
Content-Type: application/json

{"amount_cents":2500}

Pending funding returns 402, WWW-Authenticate: Payment ..., and a body containing id, amount_cents, currency, status, created_at, expires_at, payment_url, and payment_challenge. The returned payment_url is an API path relative to the REST origin. Have your payment client process the challenge. Keep the account bearer credential in Authorization; submit the resulting payment credential separately:

POST /api/v1/account/funding/FUNDING_ID
Authorization: Bearer ACCOUNT_CREDENTIAL
Payment-Authorization: Payment WALLET_GENERATED_CREDENTIAL

Use the exact credential produced for this challenge. Never send a wallet private key, seed phrase, or raw card details. GET /api/v1/account/funding/FUNDING_ID checks and reconciles status; it can return 402 while still pending. Confirm status == "funded" and GET /api/v1/accounts/credits before starting a run. Provider confirmation and duplicate handling precede ledger crediting.

Retry the same amount with the same Idempotency-Key; a different amount under that key returns 409 funding_conflict. Other errors include 400 invalid_funding_request, 400 payment_verification_failed, 404 not_found, and 410 payment_challenge_expired. An expired challenge requires a new intent; inspect the prior payment before paying again.

The Hermes payment skill and Stripe MPP documentation describe payment-client setup. All Amnetic request fields needed for funding are specified here.

Runs

Quote before submitting

Request GET /api/v1/clean-rooms/ROOM_ID/run-price as a member with access. The server sets the run shape and fee by room data size (up to 25 MB: $10, c.large, 30 minutes; up to 10 GB: $250, c.large, 120 minutes; up to 100 GB: $500, c.xlarge, 240 minutes). So the quote and run requests take no machine or runtime fields, and a request that sends machine_size or max_runtime_minutes is refused.

A quote includes currency, price_schedule_version, machine_size and max_runtime_minutes (the server-set run shape), expected_charge, flat_fee_micro, usage_cap_micro, reserved_now_micro, usage_charged, payer, charged_on, released_by, tier, and estimated_egress_usd. It carries numbers and machine-readable values only, no sentences. Money fields are integer micro-USD: expected_charge is charged only if the report is released, and reserved_now_micro is held from your spendable credit when the run starts (0 for an invoice-billed account, which is invoiced on release instead). usage_charged is false: compute and model usage are recorded but not charged. payer is always the account that starts the run (member, or owner for the room owner's own run). charged_on is release, so any other outcome returns the hold uncharged (an invoice-billed account is not invoiced). released_by is owner when the room owner decides release, or automatic for the owner's own run, which releases and is charged when the report completes. Preserve numeric fields exactly. Runs have no separate terms to accept: the Terms accepted during account setup govern them, and a newly published Terms version should be re-accepted through the acceptance flow above.

Start analysis

POST /api/v1/clean-rooms/ROOM_ID/runs
Authorization: Bearer ACCOUNT_CREDENTIAL
Content-Type: application/json

{"request_text":"Analyze the room data against the attached scenarios. State assumptions and produce a concise report.","files":["/research/brief.md","/research/scenarios.csv"],"expected_charge":123456,"price_schedule_version":"VERSION_FROM_QUOTE"}

The charge and version must come from the current quote, not the illustrative numbers above. files is optional. Request text is bounded by 512 KiB of UTF-8; the JSON transport allows escaping overhead. Input transport has been verified with a 64,096-token provider-counted request; a completed live model analysis at that size has not been verified. The selected model must also fit room data, system instructions, tools, and output.

Save the created run's id. Run creation does not have the funding endpoint's idempotency contract: after a timeout, inspect your run list before issuing another POST. A second POST can create another request and reservation.

Status and released analysis

Method and path Purpose
GET /api/v1/clean-rooms/{id}/runs List your runs
GET /api/v1/clean-rooms/{id}/runs/{run_id} Read your run, status, billing, and released report
GET /api/v1/clean-rooms/{id}/history Read permitted room history
GET /api/v1/clean-rooms/{id}/decisions Owner's pending question/report review projections
POST /api/v1/clean-rooms/{id}/runs/{run_id}/decision Owner's question, release, or share decision

Member run fields: id, room_id, request_text, request_sha256, attachments (frozen selected file metadata), status, stage, created_at, request_expires_at, machine_size and max_runtime_seconds (the shape the run used), events; optional failure_code, owner_message, release_pending, next_deadline, report, receipt, cost, and billing. A released report contains text and sha256. Raw reports are unavailable to members before release. Do not treat report_ready as permission to read protected report bytes.

Progress states are requested, analysis_approved, running, and report_ready. Success is released. Other terminal states are denied_at_request, no_response_at_request, cancelled, listing_unavailable, listing_changed, failed, denied_at_release, and no_response_at_release; some retained wire names use listing for the underlying protected source snapshot. Treat unknown states conservatively and inspect the response instead of assuming success.

Run lists, history, and decision lists use {"data":[...]}. Owner decision entries contain run_id, member_email, gate, attachments, applicable request_text/request_sha256 or report_text/report_sha256, pinned_content_sha256, screen_flags, released_bytes_this_handle, released_bytes_listing, and optional report_diff. Frozen attachment metadata contains attachment_id, filename, size_bytes, and sha256; these are output metadata, not input IDs for run creation.

Poll at a modest interval with backoff and stop on terminal states. Waiting for owner approval is expected; it is not an error to fix by resubmitting. The owner may review the frozen question/files, then the generated report and review aids.

An owner decision body is {"gate":"question","decision":"approve","echoed_sha256":"REQUEST_HASH_FROM_DECISION","message":"Optional explanation"} or {"gate":"release","decision":"approve","echoed_sha256":"REPORT_HASH_FROM_DECISION"}. Use deny to decline a gate. Echo the exact current hash: it prevents approving content that changed since review. Successful decisions return {"id":"RUN_ID","room_id":"ROOM_ID","gate":"question","decision":"approve","release_pending":false}.

The owner signed in to the portal can always decide. An API key can decide only after the owner, signed in to the portal, grants that key decision permission (the API keys section of the portal, which sends PATCH /api/v1/accounts/api-keys/{id} with {"decision_authority":"deciding"}). Keys have no decision permission by default, and a key cannot grant it to itself or another key. An amnetic login (CLI) token is not a portal sign-in: it cannot decide (403 decision_permission_required) or grant decision permission (403 session_required), though it keeps the owner's other access. A key without it gets 403 with code decision_permission_required, whichever room it names. The same rule applies to the MCP tool decide_clean_room_run; MCP connector (browser OAuth) sessions cannot decide. The owner's /history lists each run's decisions with decided_by (session or api_key) and api_key_id.

Other account operations

These shared account endpoints are also visible to cleanroom accounts:

API Request and response
GET /api/v1/account/profile Own account_id, optional business_description, website, display_name, and is_test
PUT /api/v1/account/profile {"business_description":"Research","website":"https://example.com","display_name":"Agent"}; own updated profile
GET /api/v1/profile Shared Terms vocabulary: profile, profile_sha256, terms, ordering, closure_rules, context, scenarios, versions, and instruments
PATCH /api/v1/accounts/api-keys/{id} Optional publish_authority and spending_authority; update own key's supported authorities. Or decision_authority alone ("deciding" or ""): grant or remove a key's cleanroom decision permission; owner signed in to the portal only (not amnetic login)

Terms status/acceptance, API-key create/list/revoke, balance, browser checkout, machine funding, and machine sizes are specified above. These are account prerequisites, not additional product workflows. Availability is server-enforced; client navigation does not grant authority.

MCP

Connect an HTTP MCP client to https://market.amnetic.ai/mcp. Use browser OAuth if the client supports it, or send an ordinary account API key as the bearer header. A generic MCP initialization uses JSON-RPC initialize, then notifications/initialized; discover the available schema with tools/list and invoke with tools/call. For example, send this initialization body over HTTP POST with Authorization: Bearer YOUR_ACCOUNT_KEY, Content-Type: application/json, and Accept: application/json, text/event-stream:

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"cleanroom-client","version":"1.0"}}}

Read the negotiated result.protocolVersion and any Mcp-Session-Id response header. On subsequent POSTs send that MCP-Protocol-Version and session ID, the same bearer and content/accept headers, first with {"jsonrpc":"2.0","method":"notifications/initialized"}, then {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}. Honor JSON or event-stream responses. Do not hardcode tool discovery as authorization.

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_clean_rooms","arguments":{}}}

The complete cleanroom/account tool set is below. Required values are shown unless marked optional. Outputs follow the corresponding REST projection; MCP content is returned in the SDK's tool-result envelope and may include structuredContent. Check isError before consuming it.

Tool Arguments
create_clean_room title
list_clean_rooms {}
get_clean_room room_id
delete_clean_room room_id, confirm_title (the exact room title); owner, permanent; OAuth-connected MCP only, API keys are refused as on REST
grant_clean_room_access room_id, email
set_clean_room_open_join room_id, enabled; owner
join_clean_room room_id
list_clean_room_decisions room_id; read-only, owner
decide_clean_room_run room_id, run_id, gate, decision, echoed_sha256, optional message; owner, API key with decision permission only
list_clean_room_files room_id, path; owner
read_clean_room_file room_id, path; owner, base64 output up to 5 MiB
write_clean_room_file room_id, path, content_base64; owner, at most 5 MiB encoded, use REST for larger writes
delete_clean_room_file room_id, path; owner
list_files path
read_file path; output path, content_type, content_base64
write_file path, content_base64, optional content_type; at most 25 MiB decoded
delete_file path; output {"deleted":true}
quote_clean_room_run room_id
start_clean_room_run room_id plus every field in the REST run creation body
get_clean_room_run room_id, run_id
get_account_credits {}
create_account_funding amount_cents, idempotency_key
get_account_funding funding_id
pay_account_funding funding_id, payment_credential
get_my_profile {}
update_my_profile business_description, website, display_name; empty strings clear fields
get_terms_vocabulary {}

MCP does not provide account signup, access revocation, room closure, or a complete run-list/history replacement; use the REST operations above for these. Scoped evaluator tools such as task/report submission are runtime-only and are not part of this integration flow.

Errors and retries

Response Handling
413 request_text_too_large Text exceeds max_bytes:524288; reduce it, never truncate silently
400 / 422 Fix the invalid field, path, size, or missing run consent; do not retry unchanged
401 Renew authentication; use a Cognito ID token or supported account key
402 funding Expected MPP payment challenge; process it with the payment client
402 insufficient_credit Check balance/reservations and fund before resubmitting
403 Account not provisioned, scope, Terms, or authority failure; inspect error code
404 Resource absent or inaccessible; do not probe other identities
409 Idempotency/content/state conflict; reread current state before retrying
412 tos_version_changed Read and accept the current Terms instrument
429 Back off; honor Retry-After when supplied
5xx / transport timeout Back off; reconcile state before repeating money or run creation

Error responses may carry error, code, and message; preserve the received code for diagnostics without logging credentials or source data. 409 price_stale returns fresh expected_charge and price_schedule_version; fetch a complete fresh quote and authorize it. 409 evaluation_decision_stale returns current content hashes and status; rereview content before deciding. Do not treat retries as permission to accept new Terms or prices automatically.

Complete integration sequence

  1. Call Cognito SignUp, read the email code, ConfirmSignUp, and InitiateAuth exactly as shown above.
  2. Use AuthenticationResult.IdToken to POST /api/v1/accounts, read /account/tos-status, review its instrument, and post /account/tos-acceptances with that version.
  3. Create and securely save an account API key; connect MCP or keep using REST.
  4. Create a room as owner, add a room source file through raw PUT, and grant access to the requesting member's verified email. The member repeats steps 1–3 for its own account if needed.
  5. As the member, write /research/brief.md through PUT /api/v1/files/research/brief.md. Do not write protected room data through a member credential.
  6. Read credits. If insufficient, create one funding intent, pay its returned challenge with the authorized client, reconcile that same intent, and confirm the credited balance. Do not proceed while pending.
  7. Obtain the room's current run quote, review it, and submit one run using that quote plus files:["/research/brief.md"].
  8. As the owner, read /decisions and approve the question with the current request hash. The member polls its saved run ID.
  9. When the report is ready, the owner reviews it and approves release with the current report hash.
  10. The member reads GET /api/v1/clean-rooms/ROOM_ID/runs/RUN_ID, checks status == "released", and consumes report.text. Keep report.sha256 and the receipt if needed. Stop polling on success or another terminal status.

The same verified account can run an agent integration; the owner/member approval boundaries still apply. This sequence requires a working evaluator runtime and owner approval, not merely successful HTTP requests.