# T3OS Developer Platform: Integration Guide Canonical public, agent-readable guidance for https://dev.t3os.ai. Last updated with the developer portal deployment. This guide is an orientation and safety contract; the live MCP planning contract and GraphQL schema remain authoritative. ## 1. Rules for coding agents 1. Connect to the T3OS MCP server. The current developer portal gives its environment-specific URL; do not assume an app-domain MCP proxy. 2. Call `get_t3os_planning_contract` with `targetSurface: "mcp"` and `appKind: "WORKSPACE_INSTALLED"` unless the integration truly must act as individual users. 3. Fill in the integration goal, workspace/project context, data involved, users, auth model, deployment target, and validation checks. 4. Call `review_t3os_plan`. Treat `requiredFixes`, `validationChecks`, and `openQuestions` as the implementation checklist. Re-submit after material fixes. 5. Query the live GraphQL schema or explorer for exact types, fields, and permissions. Do not guess API shapes. Keep secrets out of prompts, code, logs, and reviews. Use placeholders: ``, ``, ``, ``, ``, and ``. ## 2. Choose an application and auth model ### WORKSPACE_INSTALLED — default for agents and servers An administrator installs the app once for a workspace. It then runs server-to-server with workspace-scoped authority. Choose this for backend integrations, ETL, scheduled syncs, agents, and webhook consumers that do not represent one signed-in user. Send the credential only from trusted server-side code: ```http X-API-Key: ``` An API key is a bearer secret. Store it in a secret manager; never ship it to a browser or mobile client. Grant the fewest roles required. API key plaintext is revealed only when created or rotated; it cannot be fetched later. Rotate with an overlap only after the replacement is deployed; revoke compromised credentials immediately. ### USER_DELEGATED — per-user OAuth Use only when each user must individually authorize the integration. T3OS uses OAuth 2.0 Authorization Code with PKCE. Current registrations are confidential regular-web clients: the client secret and token exchange belong on a server, never in browser or mobile code. - Register exact HTTPS redirect URIs and minimum required workspace roles. T3OS automatically manages `openid`, `profile`, `email`, and `offline_access`; an empty workspace-role list is a sign-in-only app. - Create a cryptographically random 43–128 character verifier; use its SHA-256 base64url value as the `S256` challenge. - Generate and persist single-use `state` and `nonce` values in a short-lived encrypted HttpOnly server session; verify both. - Redirect to `https:///authorize` with `client_id`, `response_type=code`, exact `redirect_uri`, `scope`, `audience`, `code_challenge`, `code_challenge_method=S256`, `state`, and `nonce`. - Use the exact delegated audience shown on the app detail page: `https://staging-api.equipmentshare.com/es-erp-api/delegated` in staging or `https://api.equipmentshare.com/es-erp-api/delegated` in production. - When launched with `?workspace=`, forward the target as `ext-workspace-id` and require the verified `https://es-erp/workspace_id` claim to match it. Store connections by app, stable user UID, and workspace. - Include `offline_access` only when a refresh token is needed. - Exchange the returned code using the original verifier. Do not process a callback whose state does not match. - Send the delegated access token to GraphQL as `Authorization: Bearer `. T3OS reuses consent only for the exact active app/user/workspace/scope-set grant. Changed scopes, revocation, a different workspace, or `prompt=consent` requires consent again. Local logout clears only the app session; token revocation, connected-app grant revocation, and Auth0 `/v2/logout` have different effects. If the application needs identity only and no T3OS API access, use the OIDC guide in the portal instead of the workspace-bound API flow. ## 3. Verify delegated JWTs Discover endpoints rather than hard-coding them: ```text Issuer: https:/// OIDC discovery: https:///.well-known/openid-configuration JWKS: https:///.well-known/jwks.json ``` Reject a token unless all required checks pass: - `iss` exactly matches the configured issuer, including trailing slash. - `aud` contains the configured API audience. - `exp`, `iat`, and `nbf` are valid (allow only small clock skew). - `azp` is the app client ID. - Required action scope is present in the space-separated `scope` claim. - Use `https://erp.estrack.com/uid` as the stable access-token user join key (`https://es-erp/uid` in an id_token); do not use `sub` or email. - Require canonical `https://es-erp/workspace_id` to match the stored connection and requested resource. Cache the remote JWKS set across requests so normal key rotation works efficiently. ## 4. GraphQL API The exact GraphQL endpoint is shown by the developer portal for the selected environment: ```text ``` Authentication is either `Authorization: Bearer ` for a delegated user or `X-API-Key: ` for server-to-server work. Use a normal POST request with JSON body containing `query` and `variables`. Check the GraphQL `errors` array, even when the HTTP response succeeds. Useful developer-app operations include: - `myApps`: apps owned by or shared with the caller. - `app(id: String!)`: owned/collaborated app configuration. - `getAppPublicListing(appId: ID!)`: public marketplace listing. - `registerApp(input: RegisterAppInput!)`: returns a one-time `clientSecret` for confidential clients. - `updateApp(input: UpdateAppInput!)`, `rotateAppSecret(appId: String!)`, and `submitAppForReview(appId: String!)`. The full schema is the authority. Browse it at https://dev.t3os.ai/docs/explorer; schema browsing does not require credentials, but executing protected operations does. The developer-app reference does not enumerate all T3OS domain operations; always use MCP/schema discovery for those. ## 5. Custom Data Custom Data lets a workspace extend supported T3OS resources with custom fields or define reusable custom objects with their own fields and entries. Contacts are the first supported core resource; discover current support with `customFieldResourceTypes` rather than hard-coding resource types. - Use a custom field when a value belongs directly to a core resource, such as a Contact's date of birth, customer tier, or manager. - Use a custom object when the data has its own identity or should be referenced by multiple records, such as a service site. - Discover types, valid cardinalities, reference targets, identifier rules, and limits with `customFieldDefinitionConfiguration` or `customObjectConfiguration` before rendering configuration UI. - Supported types are `SHORT_TEXT`, `LONG_TEXT`, `BOOLEAN`, `INTEGER`, `DECIMAL`, `DATE`, `DATE_TIME`, `URL`, `ENTITY_REFERENCE`, and `CUSTOM_OBJECT_REFERENCE`. Values cross GraphQL as canonical strings. `ONE` uses `value`; `MANY` uses an ordered `values` list. - `ENTITY_REFERENCE` stores the target core resource ID and declares `validation.referenceResourceType`. `CUSTOM_OBJECT_REFERENCE` stores an entry ID and declares `validation.objectDefinitionId`. - Select `referenceTargets` to obtain caller-authorized display metadata. Preserve raw IDs and handle `RESOLVED`, `ARCHIVED`, and `UNAVAILABLE` explicitly. - Configure a custom object's `titleFieldKey` from a `ONE SHORT_TEXT` field. Read `displayLabel` for people-facing UI; it falls back to the entry handle. The API requires a unique handle on entry creation even when product UI generates it automatically. - Use `expectedAbsent` for a first field-value write and the last-read `expectedRevision` for replacements, deletion, schema changes, archives, restores, and entry changes. Reload and reconcile stale revisions; do not blindly overwrite. - Contact custom-field filters and sorting are eventually consistent. Confirm writes from mutation results or canonical reads. - Request `custom_data_definition_creator` to manage custom field definitions and `custom_object_definition_creator` to manage custom object definitions/entries, plus the owning resource's required reader or manager role. Complete concepts, examples, lifecycle rules, and copy-paste GraphQL operations: https://dev.t3os.ai/docs/custom-data. ## 6. Webhooks T3OS uses the Svix App Portal for endpoint configuration, delivery attempts, and replay. Configure it through the app detail page; no separate Svix account is needed. 1. Register or open the developer app. 2. Add a public endpoint controlled by the service, then subscribe only to needed event types. 3. Save the endpoint signing secret in a secret manager. 4. Verify every delivery before parsing, persisting, or acting on the event. Verification must use the unchanged raw request body, the endpoint signing secret, and all three headers: `svix-id`, `svix-timestamp`, and `svix-signature`. Use an official Svix library. Return a non-success status for invalid signatures. Make processing idempotent using the delivery/event identity, handle retries, and use the Svix portal for inspection or replay. Event names and payload schemas are environment-specific. Use the event catalog linked from https://dev.t3os.ai/docs/webhooks rather than inventing schemas. ## 7. Copy-owned UI components T3OS publishes optional React components through the public shadcn GitHub registry at https://github.com/EquipmentShare/t3os-ui-registry. Registry installation copies source into the consuming application; it does not add a T3OS runtime dependency and updates never propagate automatically. Inspect source before installation and review diffs before syncing a later revision. The account workspace menu accepts display-safe workspace and user metadata plus application-owned URLs. Derive its current workspace from the verified app session, pass only authorized connected workspaces, and keep tokens, API keys, client secrets, and private configuration out of props. Workspace links must start the application's workspace-targeted T3OS authorization or install flow; changing local UI state never grants authority. Its sign-out action must be a local POST endpoint. Interactive preview, installation commands, contract, theming, and update workflow: https://dev.t3os.ai/docs/ui-components. ## 8. Public browser documentation - https://dev.t3os.ai/docs — overview and application kinds - https://dev.t3os.ai/docs/oauth — delegated OAuth + PKCE - https://dev.t3os.ai/docs/oidc — sign in with T3OS - https://dev.t3os.ai/docs/api-keys — workspace credentials and rotation - https://dev.t3os.ai/docs/jwks — token verification - https://dev.t3os.ai/docs/webhooks — Svix delivery setup - https://dev.t3os.ai/docs/custom-data — custom fields, custom objects, references, values, and lifecycle - https://dev.t3os.ai/docs/ui-components — copy-owned UI preview, installation, and integration contract - https://dev.t3os.ai/docs/graphql — developer-app GraphQL reference - https://dev.t3os.ai/docs/explorer — live GraphQL schema explorer - https://github.com/EquipmentShare/t3os-examples — public OAuth, OIDC, and workspace-installed reference apps - https://github.com/EquipmentShare/t3os-ui-registry — public copy-owned UI registry ## 9. Discovery endpoints - https://dev.t3os.ai/robots.txt - https://dev.t3os.ai/sitemap.xml - https://dev.t3os.ai/llms.txt - https://dev.t3os.ai/llms-full.txt