# ONE > ONE is GeoTech's Firebase-hosted internal operational workspace. It exposes a public HTTP API reference and one remote MCP server at /api/mcp: people sign in with OAuth, approved services send a permanent ONE API key, and every call follows the signed-in identity's live role, board grants, and scopes. MCP client guide: https://one.geotech.one/docs/mcp/ Remote OAuth MCP: https://one.geotech.one/api/mcp ## Public Docs - Human docs: https://one.geotech.one/docs/api - OpenAPI: https://one.geotech.one/openapi/geocrm.json - MCP manifest: https://one.geotech.one/mcp/geocrm.json - App: https://one.geotech.one - Branding: https://one.geotech.one/branding - Windows installer: https://one.geotech.one/install.ps1 - Windows uninstaller: https://one.geotech.one/uninstall.ps1 - Ubuntu installer: https://one.geotech.one/install-ubuntu.sh ## OneClient Windows Commands Install or repair the centrally distributed Windows client. This requests one UAC approval when needed: ```powershell irm https://one.geotech.one/install.ps1 | iex ``` Remove the local Windows service, tray, binaries, updater data, and config. Remove the retained offline inventory card separately in the authenticated ONE UI: ```powershell irm https://one.geotech.one/uninstall.ps1 | iex ``` ## OneClient Ubuntu Command Install or repair the centrally distributed Ubuntu AMD64 client as a hardened systemd service: ```bash curl -fsSL https://one.geotech.one/install-ubuntu.sh | sudo bash ``` ## HTTP API Base URL: https://one.geotech.one/api Availability: API-key mode requires the Firebase Function behind /api/**. If GET /health returns 404, the Function is not deployed; deploy it or develop against the Firebase Emulator Suite. Agents never fall back to direct Realtime Database access: the MCP surface operates only on ONE data through the Function's authorization path and holds no Firebase or Google Cloud project credentials. Authentication: - Authorization: Bearer - X-GeoCRM-Key: Core endpoints: - GET /health - GET /info (canonical app URLs and docs links; public) - GET /branding (authoritative GeoTech logos, exact palette, typography, patterns, four-page digital design system, all 89 design variables, resources, and agent usage rules; public) - GET /decks (list draft and published client decks; decks:read or owner/admin access required) - GET /decks/{slug} (read the mutable draft and current immutable publication metadata) - PUT /decks/{slug} (create or replace a revision-bound structured draft without a repository checkout) - PUT /decks/{slug}/access (set or remove optional server-enforced passcode access) - POST /decks/{slug}/access-setup (create a one-time browser URL so an MCP client never handles the passcode) - POST /decks/{slug}/assets (upload a private JPEG, PNG, WebP, or MP4 asset) - POST /decks/{slug}/publish (snapshot the current ONE brand contract and publish an immutable web/PDF revision) - POST /decks/{slug}/unpublish (remove public access while retaining drafts, assets, and history) - GET /decks/public/{slug} (serve the immutable web-deck source; public or passcode session) - GET /decks/public/{slug}/pdf (serve the synchronized branded PDF through the same access boundary) - GET /machines/client/latest (signed OneClient release manifest; public) - GET /machines/client/releases/{version}/{platform}/{arch}/{fileName} (OneClient release artifact; public) - PATCH /machines/{machineId}/color (set the global machine/calendar color; Firebase ID token and admin access required) - PATCH /machines/{machineId}/role (classify aliases as a bookable graphics machine or non-bookable runner; Firebase ID token and admin access required) - DELETE /machines/{machineId} (archive a remote machine after exact current-name confirmation; aliases are resolved server-side; Firebase ID token and owner/admin access required) - GET /administration/audit (redacted access, grants, invitations, and API-key metadata audit; Firebase owner/admin only; API keys rejected) - GET /me - GET /team/requests (Firebase-user Personal Workspace: own profile, BambooHR-mirrored time off and full history, assigned hardware, request history, and direct-report approvals; API keys are rejected) - GET /team/time-off/admin (ONE owner/admin time-off settings, assignments, balances, and accrual state) - GET /team/time-off/people/{personId}/history (ONE owner/admin complete employee ledger with accrual, request, carryover-loss, adjustment, balance, and policy categories) - GET /logs (seven-day diagnostic history; filter by from, to, level, category, connector, source, q, limit) - POST /logs (write a short-lived diagnostic log; requires write scope) - GET /boards (board revisions for every reader; board-directory reorder context for ONE owners/administrators) - POST /boards (create a standard Table-only public board; owner/admin personal auth and current directory revision required) - POST /boards/reorder (preview by default or apply the complete board order; owner/admin personal auth and current directory revision required) - GET /boards/{boardId} (includes the canonical structural revision) - PATCH /boards/{boardId} (rename a non-protected board; owner/admin personal auth and current board revision required) - DELETE /boards/{boardId} (remove a confirmed non-protected board from the active workspace; owner/admin personal auth and current revision required) - POST /boards/{boardId}/columns (create or return a board column; owner/admin personal auth and current board revision required) - PATCH /boards/{boardId}/columns/{columnId} (rename a non-protected column and synchronize embedded item-cell labels; owner/admin personal auth and current board revision required) - DELETE /boards/{boardId}/columns/{columnId} (archive a confirmed non-core column while preserving item cell data; owner/admin personal auth and current board revision required) - GET /boards/{boardId}/items - POST /boards/{boardId}/items - GET /boards/{boardId}/items/duplicates - GET /boards/{boardId}/items/{itemId} - GET /search?q=... (searches all boards by default; optional board_id scopes to one board) - POST /contacts (create/update a contact and link an existing or newly created company) - GET /contacts/duplicates - POST /boards/{boardId}/items/move (move filtered items to another group; supports dry_run) - PATCH /boards/{boardId}/items/{itemId} - DELETE /boards/{boardId}/items/{itemId} - POST /boards/{boardId}/items/{itemId}/duplicate (revision-bound duplicate with a new identity; ONE-managed private file references and protected owner assignment are not copied) - POST /boards/{boardId}/items/duplicates/merge - GET /boards/{boardId}/items/{itemId}/files (list private item-file metadata; current board read access required) - POST /boards/{boardId}/items/{itemId}/files (append a validated raw PDF/image/Office/CSV/JSON/text/ZIP file up to 20 MB; use X-File-Name, X-Column-Id, and optional X-Column-Title; write access required) - POST /boards/{boardId}/items/{itemId}/files/import-drive (copy a Google Drive or native Docs/Sheets/Slides file into ONE private storage; Firebase session and connected matching Google account required) - GET /boards/{boardId}/items/{itemId}/files/{fileId} (authenticated checksum-verified private file stream) - DELETE /boards/{boardId}/items/{itemId}/files/{fileId} (permanently remove the managed item file and its private object; write access required) - GET /item-files/drive/accounts and POST /item-files/drive/authorization (session-bound Google Drive readiness and in-context OAuth authorization for board file imports; Firebase user required and the Google email must match the ONE session) - POST /boards/{boardId}/items/{itemId}/updates - PATCH /boards/{boardId}/items/{itemId}/updates/{updateId} (edit a revision-bound update; author or ONE owner/admin only) - DELETE /boards/{boardId}/items/{itemId}/updates/{updateId} (delete after exact-text and revision confirmation; author or ONE owner/admin only) - POST /contacts/duplicates/merge - POST /task-automation/assign (Firebase-authenticated browser assignment or @Codex mention; assigns the task to the Codex agent for manual MCP pickup, or unassigns it) - POST /backups (queue a compact or full background backup; backups:write or Firebase owner auth) - GET /backups?limit=25&cursor=... (list safe newest-first backup metadata without protected workspace/data-root payloads; backups:read or Firebase owner auth) - GET /backups/{backupId} (read safe coverage metadata for one backup; backups:read or Firebase owner auth) - GET /backups/{backupId}/export (download the import-compatible protected JSON envelope; signed-in Firebase owner only, never API keys; 30 MiB HTTPS limit) - GET /backups/jobs/{jobId} (poll status and completed backup metadata; backups:read or Firebase owner auth) - GET /documents/sign-requests (list private e-signature agreements; documents:read or Firebase Documents user) - POST /documents/sign-requests (raw PDF/image upload with X-File-Name, X-Document-Name, X-Signers, X-Subject, X-Message, and X-Settings; documents:write) - GET|PUT /documents/sign-requests/{requestId} (read or update a draft's recipients, actions, routing, message, reminders, and expiration) - POST /documents/sign-requests/{requestId}/documents (add a raw PDF/image document to a draft; 10 documents maximum) - DELETE /documents/sign-requests/{requestId}/documents/{documentId} (remove a draft document and its placed fields; at least one source must remain) - GET /documents/sign-requests/{requestId}/file?kind=source|combined|signed (read a verified private original, combined PDF, or completed signed PDF; optional document_id selects a source) - PUT /documents/sign-requests/{requestId}/prepare (place signature, initials, text, name, email, title, date-signed, and checkbox fields) - POST /documents/sign-requests/{requestId}/send (send private links in parallel or configured routing order; documents:send) - POST /documents/sign-requests/{requestId}/resend|refresh|void (rotate one recipient link, refresh native state, or void a live agreement) - DELETE /documents/sign-requests/{requestId} (delete a draft or terminal agreement and its private files; live agreements must be voided first) - GET /documents/sign-templates and POST /documents/sign-requests/from-template (list and use reusable agreements) - POST /documents/sign-requests/{requestId}/template (save a prepared draft as a reusable template) - DELETE /documents/sign-templates/{templateId} (delete a reusable template and its private document copies) - GET|POST /hardware/boards/{boardId}/assets (list canonical Hardware inventory or create an audited asset; Firebase OAuth plus Hardware view/edit access) - GET|PATCH|DELETE /hardware/boards/{boardId}/assets/{assetId} (read, revision-update, or archive an asset; archival releases custody and requires exact asset-ID confirmation) - POST /hardware/boards/{boardId}/assets/{assetId}/move (idempotent revision-bound custody transfer with immutable movement history) - GET|POST /hardware/boards/{boardId}/assets/{assetId}/documents (list safe metadata or upload a private PDF/image up to 20 MB) - GET|DELETE /hardware/boards/{boardId}/assets/{assetId}/documents/{documentId} (checksum-verified private download or deletion using current revision and exact file name) - GET|POST /people/boards/{boardId}/items/{itemId}/documents and GET|DELETE /people/boards/{boardId}/items/{itemId}/documents/{documentId} (person-folder private document lifecycle; Firebase OAuth plus explicit People Documents view/edit access; column_id is required) - GET|POST /people/boards/{boardId}/documents and GET|DELETE /people/boards/{boardId}/documents/{documentId} (People company-link private document lifecycle with the same explicit grant and guarded deletion) Assigning Codex sets the virtual Codex assignee and a queued marker on the task. No worker job is created; a human copies the shareable task link and hands it to Codex manually. - GET /task-projects/boards (least-privilege project-task board discovery; tasks:read) - GET /task-projects/boards/{boardId}/projects (least-privilege project summary discovery; tasks:read) - GET /task-projects/boards/{boardId}/projects/{projectId} (one safe project summary; tasks:read) - GET /boards/{boardId}/projects/{projectId}/tasks (legacy task list by default; set tracking_context=true with exact tasks:read for revision-bound tracker context: stable task pages, configured statuses, sprints, milestones, up to 12 exact People matches, opaque cursor, and project_revision; limit 1-100; the safe ledger is capped at 500 returned records, so inspect import_records_total and import_records_truncated) - POST /boards/{boardId}/projects/{projectId}/tasks (typed tracker import: 1-12 retry-safe tasks with expected_project_revision, immutable import keys, canonical People references, explicit scheduling/status fields, structured work links, and created/existing outcomes; service tasks:create requires a configured non-empty exact allowedProjects list; non-Backlog also needs tasks:import_status; tracker imports skip enrichment; whole-request conflicts return 409) - PATCH /boards/{boardId}/projects/{projectId}/tasks (narrow exact-project tracker update: 1-12 complete tracker-managed task records with expected_project_revision, immutable update keys, and updated/existing outcomes; tasks:create plus a configured non-empty exact allowedProjects list; comments, attachments, hidden work-link metadata, and unrelated server fields are preserved; tasks:import_status is not required; whole-request conflicts return 409) - POST /boards/{boardId}/projects/{projectId}/milestones:upsert (transactional import: 1-100 mirrored milestones with expected_project_revision, rationale, retry-safe import keys, and created/existing outcomes; service tasks:milestones:write plus an exact project allowlist; whole-request conflicts return 409) - GET|POST /boards/{boardId}/projects/{projectId}/calendar (inclusive overlap listing with item_type, or revision-bound create; service reads use tasks:read and writes use tasks:calendar:write plus an exact project allowlist) - GET /boards/{boardId}/projects/{projectId}/calendar/sources (privacy-safe roster time-off/company sources surfaced read-only in the project calendar; tasks:read plus an exact project allowlist for service keys) - PATCH|DELETE /boards/{boardId}/projects/{projectId}/calendar/{itemId} (stable-ID move/edge-resize/rename or exact-current-title deletion; both require revision and idempotency key; service deletion additionally requires tasks:calendar:delete) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId} (complete developer-task context; tasks:read) - PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId} (revision-safe task update; tasks:write) - GET/PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId} (full subtask context/update) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId}/images/{assetId} (authenticated task image; tasks:read) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId}/attachments/{assetId} (authenticated task attachment; tasks:read) - GET /boards/{boardId}/projects/{projectId}/tasks/{taskId}/subtasks/{subtaskId}/attachments/{assetId} (authenticated subtask attachment; tasks:read) - POST /boards/{boardId}/projects/{projectId}/tasks/{taskId}/attachments (upload PDF or UTF-8 text document; tasks:write or assigned personal task) - POST /boards/{boardId}/projects/{projectId}/tasks/{taskId}/comments (Codex task comment; tasks:comment) - PATCH /boards/{boardId}/projects/{projectId}/tasks/{taskId}/review-state (In Progress or Review only; tasks:review) - GET /accounting-tax/overview?year=2025|2026 (owner-only Dutch BV and DGA planning overview; separates forecasts, provisions, filed amounts, assessments, settlements, tax receivables, gross company debts, and UBO/employee/external lending; statutory filing disabled) - PUT /accounting-tax/scenarios/{year} (owner-only audited corporate-tax bridge with versioned 2025/2026 Dutch VPB rates) - PUT /accounting-tax/dga/{year} (owner-only restricted customary-salary, shareholder current-account, excessive-borrowing, dividend-withholding, and indicative Box 2 controls) - POST/PATCH /accounting-tax/obligations[/{id}] and /accounting-tax/debts[/{id}] (owner-only audited obligation and gross-debt registers) - POST/PATCH/DELETE /accounting-tax/loans[/{id}] and POST /accounting-tax/loans/{id}/movements (owner-only audited lending facilities, terms, guarded recoverable deletion, drawdowns, principal repayments, interest charges, and interest payments) - MCP exposes the Accounting & Tax overview, audit trail, close controls, lending lifecycle, and six owner-person-only lifecycle operations: accounting_tax_save_dga, accounting_tax_create_obligation, accounting_tax_update_obligation, accounting_tax_create_debt, accounting_tax_update_debt, and accounting_tax_refresh_corporate_tax_forecast. The six sensitive operations require a signed-in ONE owner OAuth session; service API keys cannot list or call them. Read the selected-year overview first, preserve exact minor-unit values and evidence, pass current revisions, keep obligations in their fiscal year, and never describe a refreshed forecast as a filing or tax advice. - POST /finance/forecast/view (deterministic 13-week or 12-month cash outlook with Base/Upside/Downside scenarios, liquid or treasury scope, dated account-balance anchoring, distinct outstanding Accounts Receivable payment drivers, approved Accounts Payable committed outflows, approval-pending A/P exposure that remains excluded from cash until approved, scope-boundary cash movement, 12 monthly manual-verification buckets, historical FX provenance, and quality warnings; finance:read, read, write, or Firebase Finance user auth) - POST /finance/forecast/events (create an idempotent one-off or recurring cash plan; finance:write, write, or Firebase Finance user auth; requires X-Idempotency-Key) - PATCH /finance/forecast/events/{eventId} (edit, archive, or restore a plan with expectedUpdatedAt optimistic concurrency; finance:write, write, or Firebase Finance user auth) - PUT /finance/forecast/settings (update the minimum-cash threshold and default scope/horizon with optimistic concurrency; finance:write, write, or Firebase Finance user auth) - POST /finance/view (bounded Finance transaction matching; finance:read or Firebase Finance user auth) - GET /cloud-costs/summary?month=YYYY-MM[&refresh=1] (protected Google Cloud and OpenRouter aggregates; Cloud Costs viewer access reads, editor access may force refresh) - POST /finance/balance-screenshots (raw transient ING account, ING credit-card, or Wise screenshot; Gemini recognition plus deterministic known-account matching adds dated balances; ING investment Belegd/Gelddeel values persist as invested/available-cash components and only available cash enters cash forecasts; credit cards use Current balance only, including zero, and normalize displayed debt as negative; finance:write, write, or Firebase Finance user auth; optional X-Balance-Date; raw image is never stored) - GET|POST /finance/bills (list or create Accounts Payable bills; positive bill totals may contain signed line-item credits; writes require a stable X-Idempotency-Key) - PATCH /finance/bills/{billId} (revision-checked AP edits; paid uploaded invoices accept workMetadataOnly corrections to supplier name, issue/due dates, line people/projects/hours, and work allocations while invoice number, descriptions, financial, payment, lifecycle, and source fields remain immutable) - GET /finance/bills/aging, DELETE /finance/bills/{billId}, and POST /finance/bills/{billId}/approve|unapprove|reject|cancel|match|unmatch (AP aging, guarded deletion of uncommitted rows with source scans preserved, approval, and outgoing-bank matching; finance:read/finance:write or Firebase Finance user auth) - POST /finance/bills/bulk-approve and POST /finance/bills/rematch (bounded approval and bank reconciliation batches; finance:write or write scope) - GET|POST /finance/invoices (list or create Accounts Receivable invoice drafts; writes require a stable X-Idempotency-Key) - POST /finance/invoices/import (Gemini extraction from a raw PDF/image into a review-required AR draft; duplicate source files reuse their existing draft) - GET /finance/invoice-customers and GET /finance/accounts (Companies customer picker and invoice-ready Finance payment accounts) - PATCH /finance/accounts/{accountId}/payment-details (owner-only BIC/SWIFT, IBAN, or account-number maintenance) - GET /finance/invoices/aging and POST /finance/invoices/{invoiceId}/issue|revise|void|paid|match|unmatch (AR aging, immutable sequential issue, safe unsent revision/void, audited manual-paid status, and guarded incoming-bank matching) - GET /finance/invoices/{invoiceId}/preview (authenticated non-numbered draft preview or inline current immutable PDF) - GET /finance/invoices/{invoiceId}/pdf (authenticated immutable issued-invoice PDF download) - POST /finance/invoices/{invoiceId}/send (Gmail delivery with PDF attachment and delivery audit; finance:invoices:send or write scope) - GET|PATCH /finance/invoice-settings (read issuer/payment/numbering configuration; updates are owner-only and issuer VAT is optional) - POST /finance/exports/journal.csv (bounded canonical journal CSV with formula-injection protection; finance:read, read, write, or Firebase Finance user auth) - GET /finance/exports/drive/accounts and POST /finance/drive/authorization (session-locked Drive readiness plus in-context Google authorization; the server exchanges the one-time code, requires the Google email to equal the Firebase session email, stores a dedicated per-user refresh token, and never returns tokens to the browser; API keys are rejected) - POST /finance/drive/browser, POST /finance/drive/destination/verify, and POST /finance/drive/destination/create (server-side My Drive/Shared Drive folder browsing and idempotent creation of one new app-owned destination folder; requires drive.file plus drive.readonly and explicit canAddChildren before and after creation; API keys are rejected) - GET|POST /finance/exports/drive and GET /finance/exports/drive/{exportId} (Finance-protected monthly immutable Google Drive/Shared Drive export history, queued background creation, and status polling; POST returns 202 immediately, creates only ONE-owned folders/files, and never changes old Drive content; Firebase Finance editor/owner required for creation) - MCP finance_list_drive_accounts, finance_list_drive_exports, finance_get_drive_export, and finance_create_drive_export (OAuth-scoped account readiness, queueing, and polling for the same durable Drive export workflow; creation requires crm.write and returns before the background copy finishes) - GET /finance/transactions/{transactionId}/evidence (list private receipt/invoice metadata; finance:evidence:read or Firebase Finance user auth) - POST /finance/transactions/{transactionId}/evidence (raw validated PDF/image upload, 20 MB max; finance:evidence:write or Firebase Finance user auth; use X-File-Name, X-Evidence-Type, and stable X-Idempotency-Key headers) - GET /finance/transactions/{transactionId}/evidence/{evidenceId} (authenticated private preview/download; finance:evidence:read or Firebase Finance user auth) - DELETE /finance/transactions/{transactionId}/evidence/{evidenceId} (delete one evidence file only; finance:evidence:write or Firebase Finance user auth) - POST /finance/categorization/context (bounded approved-decision retrieval; finance:read) - POST /finance/categorization/vector-memory/stats (active embedding namespace counters; finance:read or Firebase Finance user auth) - POST /finance/categorization/vector-memory/sync (embed selected human-approved decisions or a YYYY-MM page with finance:suggest; pass `replaceExisting: true` with one transaction ID and finance:apply to remove its prior decision vector/link and generate a fresh replacement; Firebase Finance user auth is also supported) - POST /finance/categorization/vector-memory/clear (explicitly confirmed embedding-only reset; finance:apply or Firebase owner auth) - POST /finance/categorization/runs (start an audited GPT-5.6 Sol, GPT-5.6 Terra, or OpenRouter Kimi K3 run; finance:suggest) - POST /finance/categorization/suggestions (validate votes and, unless dry-run, save AI-provenance category decisions; finance:suggest) - POST /finance/categorization/retrieve (deterministically match uncategorized transactions against approved Finance vector memory; no categorization LLM call; Firebase user auth; legacy `/run-ai` alias remains accepted) - POST /finance/categorization/transactions/{transactionId}/review (mark an AI result correct/incorrect; Exclude from AI removes that transaction's vector memory and re-inclusion queues a fresh eligible replacement; finance:apply) - GET /me/work (personal-key or Firebase-user work dashboard; open assignments remain the default, while includeCompleted=true pages open and completed assignments with source-project revision/editability/status metadata; internal accounts receive company-wide active-internal focus and project-only accounts remain permission-scoped) - GET/PUT/DELETE /me/focus (identity-bound validated personal current tasks, one per project; PUT accepts only a non-Done task assigned to the caller, callers cannot nominate another person's focus, and DELETE can clear one project) - GET /team-focus?boardId={boardId}&projectId={projectId} (visible validated focus records; unfiltered internal requests are company-wide for active internal people, board-only and project-only requests remain permission-scoped, and exact project requests require read access and may include project-only participants) - GET/POST /me/agent-keys and DELETE /me/agent-keys/{keyId} (Firebase-authenticated self-service personal keys) - PATCH /boards/{boardId}/projects/{projectId}/source-control (project-editor single repository or Perforce configuration; no credentials) - POST /webhooks/github (signed GitHub push and pull-request metadata) - POST /source-events/perforce (service-authenticated sanitized changelist metadata) - GET/POST /slack/task-automation/channels/{teamId}/{channelId} (channel-to-project mapping) - GET/POST /slack/task-automation/proposals (list/create summary-only previews) - PATCH /slack/task-automation/proposals/{proposalId} (refresh a pending preview) - POST /slack/task-automation/proposals/{proposalId}/approve (apply an exact participant-approved preview) ## MCP Branding workflow: before creating or substantially revising a presentation, Complex Decision, product or website design, UI, document, report, chart, diagram, campaign, email, social post, or other visual GeoTech work, call `get_brand_standards`. Treat its approved artwork, exact values, Cover, Getting Started, Foundations, and Tokens guidance, complete Brand/Color/Scale/Typography variables, guardrails, clear-space, and contrast rules as authoritative; use only the returned ONE/Firebase-hosted asset URLs and never substitute external file links; never redraw or transform the mark. Deck publishing workflow: call `get_brand_standards`, then use `save_deck_draft` with the complete structured source. Optionally use `upload_deck_asset` with the exact current revision. `set_deck_access` returns a one-time browser setup link for passcode mode so the passcode never enters the AI conversation. Re-read the draft with `get_deck`, review its content and claim classifications, then call `publish_deck` with the exact current `draftRevision`. Service keys use the narrow `decks:read`, `decks:write`, `decks:publish`, and `decks:access-admin` scopes. ONE publishes an immutable revision at `https://decks.geotech.one/` and generates its synchronized branded PDF without cloning the repository or rebuilding Hosting. Pass the exact current published revision ID to `unpublish_deck` to remove public access without deleting the draft, private assets, or revision history. Backup workflow: create a `Backups / Codex` API key for `backups:read` and `backups:write`, call `create_backup` with compact or full mode, and poll with `get_backup_job` when needed. Use `list_backups` and `get_backup_metadata` to inspect coverage without retrieving protected payloads. Complete JSON export is deliberately person-bound: only a signed-in ONE owner can call `export_backup` (10 MiB MCP resource limit) or the owner-only HTTP download (30 MiB limit), and the response uses the same import-compatible envelope as the Backups panel. Import, restore, deletion, retention settings, and automatic-backup settings remain UI-only and must not be automated through generic database tools. Remote Machines and administration workflow: use `list_remote_machines` or `get_remote_machine` before acting. Reads and bookings follow live scheduler-board grants. `set_remote_machine_color`, `archive_remote_machine`, and `get_administration_audit` are available only to signed-in ONE owners/administrators and never to API keys. Before archive, show that ONE will hide all server-resolved aliases and clear presence, sessions, events, metrics, and bookings without uninstalling OneClient, obtain explicit confirmation, then pass the exact current machine name as `confirm_machine_name`. The administration audit is read-only and omits hashes, reusable secrets, bridge settings, connector tokens, and credentials. Do not simulate permission mutation, invitation/key management, bridge/retention settings, or client install/update/uninstall with generic tools. Documents workflow: create a `Documents / e-signature` API key and use the full MCP profile. Create with `create_signature_request` or `create_signature_request_from_template`; read first, then use `update_signature_request`, `add_signature_document`, `remove_signature_document`, and `prepare_signature_request` while the request is a draft. Review recipients, routing, subject, message, reminders, expiration, recipient download access, and the opt-in AI assistant before `send_signature_request`; explicitly confirm send and resend. Use `refresh_signature_request` for current state and `get_signature_request_file` for protected original, combined, or completed signed content. Delete draft/terminal requests and templates only with current status/version plus exact-name confirmation; void sent/delivered requests instead. Recipient-token preview, download, AI help, sign, and decline routes intentionally have no MCP tools: never use sender tools to impersonate an external signing recipient or retrieve private signing tokens. Remote BackOffice workflow: the OAuth MCP exposes the permitted BackOffice module catalog plus Finance operator workflows; Documents agreement/template lifecycle; the person-bound Procurement request, approval, comment, lifecycle, and private-attachment workflow; and full audited Hardware asset/document lifecycle. People documents are a distinct sensitive module: person and company-link list/get/upload/delete tools require person OAuth plus the explicit People Documents grant, and returned metadata omits storage paths and download tokens. Procurement, Hardware, and People writes require current module/editor access; revisions protect guarded updates/deletions; retryable Procurement and custody writes are idempotent; and destructive operations require exact confirmation. Cloud Costs is available through its protected Firebase-user HTTP summary route. Every call rechecks the signed-in user's current module grant, and Procurement also rechecks request-level visibility. Hiring intentionally remains ONE UI-only and has no API, MCP, or plugin workflow. Deck library: ONE /decks lists all deck revisions and links, with first-page grid previews and password controls. The owner can migrate legacy briefs with migrate_decision_decks; originals are retained for recovery and imported decks stay owner-only until sharing access is explicitly set. Finance forecast workflow: use the full MCP profile with a Finance-capable key. Start with `finance_get_cash_forecast`, then add retry-safe planned movement with `finance_create_cash_plan`; use the returned `updatedAt` value for update, archive, and restore operations. Forecast values are deterministic calculations from classified cash history and plans—no LLM generates financial amounts. Finance account screenshot workflow: use the full MCP profile with a Finance write-capable key and call `upload_account_balance_screenshot` with a local ING or Wise image. Gemini reads only the direct provider screen; known account matching and balance writes are deterministic. ING investment Belegd/Gelddeel values stay together as invested and available-cash components, with only available cash entering the cash forecast. Converted aggregate totals and ambiguous rows are skipped, and the raw screenshot is never stored. Slack project-task workflow: mention ONE in a channel thread and ask naturally to turn the conversation into project tasks or refresh tasks already linked to it. The bot reads the complete live thread, persists a summary-only 24-hour preview, refreshes after replies, and applies only after a thread participant approves the latest snapshot with `white_check_mark`. Store Slack permalinks on tasks, append details/comments, and preserve later human edits. Connect commands: ```text claude mcp add --transport http one https://one.geotech.one/api/mcp codex mcp add one --url https://one.geotech.one/api/mcp --oauth-resource https://one.geotech.one/api/mcp ``` Services send a permanent ONE API key instead of signing in: Authorization: Bearer on the same /api/mcp route. The visible tool list follows the key's scopes. Interactive authentication: the ONE Codex Desktop plugin installs one credential-free remote MCP connection and starts direct ONE OAuth when the user selects Authenticate. Personal ChatGPT Plus or Pro accounts with Codex access do not require a Team or Enterprise workspace or OpenAI app approval. The ONE identity used for authorization remains independent from the personal ChatGPT identity. ChatGPT web still requires the separately approved app connection. Claude, Cursor, and OpenCode retain their existing remote MCP connection packages. Advanced fallback: a controlled, user-run workflow or interactive client without working OAuth may use a 90-day Member MCP key from the `ONE_MCP_API_KEY` environment variable. The key follows its owner's live ONE role, board/project/sharing/module grants on every call and is denied immediately after expiry, revocation, user deactivation, or access removal. Unattended CI, scheduled agents, migrations, and shared integrations require a purpose-scoped service key. Never place either secret in prompts, source control, screenshots, or config files. Executable fallback templates live at https://github.com/Geodesic-Games/ONE_Codex/tree/main/plugins/one/api-key for Codex (`codex.toml` with `bearer_token_env_var`), Claude (`claude.json`), Cursor (`cursor.json`), and OpenCode (`opencode.json`). Export `ONE_MCP_API_KEY` in the environment that launches the client, remove or disable any OAuth-backed ONE connection, and install exactly one fallback definition so the client sends `Authorization: Bearer ` without storing the secret in its config. Personal focus is self-service: `set_my_focus` acts only for the signed-in person or personal-key owner and accepts only that person's assigned, non-Done task. Project leads may assign work, but no caller can nominate another person's focus; service and project-tracker keys cannot use the personal focus tools. Project-tracker workflow: use the remote /api/mcp route with OAuth, a 90-day Member MCP key, or an exact-project tracker service key. Discover exact allowed targets with `list_task_project_boards`, `list_task_projects`, and `get_task_project`. Use `list_project_tasks`, which explicitly opts into `tracking_context=true`, to read every revision-bound page; its safe import ledger is capped at 500 returned records, so callers must inspect `import_records_total` and `import_records_truncated`. Use `resolve_project_people` for exact input-level reconciliation: it distinguishes missing and multiple matches, returns IDs only for one exact active match, and requires unresolved assignees to remain null with their names retained in Details. Use `import_project_tasks` to import typed retry-safe cards, `update_project_tasks` for exact-project revision-bound updates that preserve comments, attachments, and hidden work-link metadata, and range-aware `upsert_project_milestones` to mirror milestones transactionally. Project editors and managers may import any status currently configured on the project. New tracker service keys include `tasks:read`, `tasks:create`, `tasks:milestones:write`, `tasks:calendar:write`, and `tasks:import_status` and remain restricted to one non-empty `allowedProjects` target; existing keys are not elevated automatically. Calendar parity is provided by `get_project_calendar`, `list_project_calendar_sources`, `create_project_calendar_item`, `update_project_calendar_item`, and destructive `delete_project_calendar_item`. Privacy-safe calendar sources use `tasks:read`; non-tracker exact-project service keys need `tasks:calendar:write` for mutations, and every service key needs `tasks:calendar:delete` when deletion is intended. OAuth source reads require `crm.read`; calendar mutations require `crm.write` plus editor or manager access. Member MCP and other personal keys are denied. MCP create and update calls put the action-specific item type and fields in the nested `item` payload. Calendar details are limited to 2,000 characters and color values to 20 characters. Every calendar mutation needs the current project revision and a stable idempotency key, while deletion also confirms the exact current title. The ONE calendar shows safe People sources as read-only overlays without automatically copying them; explicit REST/MCP `source_key` creation remains available to make an independent project snapshot. Reuse the same immutable key after uncertain retries, refresh after a 409, and never use generic mutations to bypass status, archive, or project boundaries. Tracker tools: - list_task_project_boards - list_task_projects - get_task_project - get_project_calendar - list_project_calendar_sources - create_project_calendar_item - update_project_calendar_item - delete_project_calendar_item - list_project_tasks - create_project_tasks - upsert_project_milestones Tools: - geocrm_health - get_current_user - get_personal_workspace - get_time_off_administration - get_person_time_off_history - update_time_off_policy - set_person_time_off_policy - adjust_person_time_off_balance - run_time_off_accruals - get_brand_standards - list_decks - migrate_decision_decks - get_deck - save_deck_draft - set_deck_access - upload_deck_asset - publish_deck - delete_deck - unpublish_deck - list_boards - get_board - create_board - rename_board - reorder_boards - list_remote_machines - get_remote_machine - set_remote_machine_color - archive_remote_machine - list_remote_machine_bookings - create_remote_machine_booking - update_remote_machine_booking - cancel_remote_machine_booking - get_administration_audit - finance_get_overview - finance_get_project_summary - finance_list_project_entries - finance_rebuild_project_summaries - finance_get_cash_forecast - finance_list_accounts - finance_list_transactions - finance_list_imports - finance_import_statements - finance_get_statement_import - finance_clear_statement_imports - finance_update_transaction_decision - finance_update_transaction_decisions - finance_list_transaction_comments - finance_add_transaction_comment - finance_update_transaction_comment - finance_delete_transaction_comment - finance_list_invoices - finance_get_invoice - finance_create_invoice - finance_update_invoice - finance_duplicate_invoice_to_draft - finance_transition_invoice - finance_void_invoice - finance_get_invoices_aging - finance_rematch_invoices - finance_get_invoice_pdf - finance_list_bills - finance_get_bill - finance_get_bill_source_file - finance_get_bills_aging - finance_create_bill - finance_update_bill - finance_transition_bill - finance_bulk_approve_bills - finance_match_bill - finance_unmatch_bill - finance_rematch_bills - finance_delete_bill - finance_list_drive_accounts - finance_list_drive_exports - finance_get_drive_export - finance_create_drive_export - accounting_tax_get_overview - accounting_tax_create_loan - accounting_tax_update_loan - accounting_tax_delete_loan - accounting_tax_record_loan_movement - list_signature_requests - get_signature_request - refresh_signature_request - get_signature_request_file - finance_revise_invoice - finance_send_invoice - finance_delete_invoice_draft - finance_get_invoice_settings - finance_update_invoice_settings - finance_get_account_payment_details - finance_update_account_payment_details - finance_get_market_quotes - finance_get_retrieval_settings - finance_update_retrieval_settings - list_signature_templates - list_hardware_inventory - get_hardware_asset - create_hardware_asset - update_hardware_asset - move_hardware_asset - archive_hardware_asset - list_hardware_documents - get_hardware_document - upload_hardware_document - delete_hardware_document - list_people_documents - get_people_document - upload_people_document - delete_people_document - list_procurement_requests - get_procurement_request - create_procurement_category - create_procurement_request - update_procurement_request - delete_procurement_request - add_procurement_approvers - add_procurement_comment - update_procurement_comment - delete_procurement_comment - decide_procurement_request - update_procurement_hardware_lifecycle - get_procurement_attachment - upload_procurement_attachment - delete_procurement_attachment - list_board_items - search_items - get_item - get_item_file - import_item_file_from_google_drive - delete_item_file - create_item - create_project_tasks - import_project_tasks - update_project_source_control - manage_project_status - manage_project_sprint - decide_task_automation_suggestion - undo_task_automation - edit_project_task_comment - delete_project_task_comment - delete_project_task_attachment - delete_project_task - update_project_tasks - update_item - add_item_update - move_board_items - delete_item - get_task_context - get_task_image - get_task_video - get_task_attachment - add_task_attachment - add_task_comment - get_task_subtask - update_task_subtask - add_task_subtask_comment - set_task_review_state - update_project_task - list_project_tasks - get_app_info - list_logs - write_log - upsert_contact - find_contact_duplicates - merge_contact_duplicates - find_board_item_duplicates - merge_board_item_duplicates - ensure_board_column - rename_board_column - archive_board_column - delete_board - set_item_file_field - get_slack_channel_project - set_slack_channel_project - list_slack_task_proposals - create_slack_task_proposal - refresh_slack_task_proposal - approve_slack_task_proposal - cancel_slack_task_proposal - list_task_project_boards - list_task_projects - get_task_project - get_project_calendar - list_project_calendar_sources - create_project_calendar_item - update_project_calendar_item - delete_project_calendar_item - resolve_project_people - upsert_project_milestones - upload_item_file - create_signature_request - create_signature_request_from_template - edit_item_update - delete_item_update - duplicate_item - update_signature_request - add_signature_document - remove_signature_document - prepare_signature_request - save_signature_template - delete_signature_template - delete_signature_request - send_signature_request - resend_signature_request - void_signature_request - upload_receipt_scan - list_receipt_scans - attach_receipt_scan - reprocess_receipt_scan - create_transaction_from_scan - finance_remap_receipt_scans - finance_purge_receipt_scans - finance_list_receipt_email_accounts - finance_scan_receipt_email - finance_create_category - finance_update_category - finance_delete_category - finance_create_subcategory - finance_update_subcategory - finance_delete_subcategory - finance_preview_fin_results - finance_import_fin_results - finance_review_fin_results_match - finance_list_transaction_evidence - finance_get_transaction_evidence - finance_upload_transaction_evidence - finance_delete_transaction_evidence - finance_verify_transaction_evidence - finance_export_journal_csv - finance_record_valuation - finance_record_balance - finance_reconcile - finance_record_investment_cash - create_time_off_request - update_time_off_request - cancel_time_off_request - update_personal_profile - create_hardware_request - decide_direct_report_time_off - get_cloud_costs_summary - upload_account_balance_screenshot - delete_finance_transactions - create_backup - get_backup_job - list_backups - get_backup_metadata - export_backup - finance_get_categorization_context - finance_start_categorization_run - finance_submit_ai_decisions - finance_review_ai_decision - finance_get_vector_memory_stats - finance_clear_vector_memory - finance_sync_vector_memory - finance_create_cash_plan - finance_update_cash_plan - finance_archive_cash_plan - finance_update_cash_forecast_settings - finance_import_invoice - finance_record_investment_portfolio - get_my_work - get_my_focus - set_my_focus - clear_my_focus - create_items - update_items - list_tool_families - set_tool_families - finance_record_account_balance - finance_issue_invoice - finance_import_bill - accounting_tax_get_audit_trail - accounting_tax_create_audit_review - accounting_tax_save_scenario - accounting_tax_save_balance_close - accounting_tax_create_balance_close_exception - accounting_tax_update_balance_close_exception - accounting_tax_create_rollforward - accounting_tax_update_rollforward - accounting_tax_create_book_to_tax_adjustment - accounting_tax_update_book_to_tax_adjustment - accounting_tax_create_tax_loss - accounting_tax_update_tax_loss - accounting_tax_refresh_book_to_tax_bridge - accounting_tax_create_related_party_reconciliation - accounting_tax_update_related_party_reconciliation - accounting_tax_refresh_related_party_snapshot - accounting_tax_create_open_item_control - accounting_tax_update_open_item_control - accounting_tax_refresh_open_item_ageing - accounting_tax_create_treasury_control - accounting_tax_update_treasury_control - accounting_tax_create_fixed_asset - accounting_tax_update_fixed_asset - accounting_tax_refresh_treasury_asset_snapshot - accounting_tax_save_annual_accounts_filing - accounting_tax_refresh_annual_accounts_readiness - accounting_tax_save_equity_position - accounting_tax_create_dividend_decision - accounting_tax_update_dividend_decision - accounting_tax_refresh_equity_dividend_snapshot - accounting_tax_save_dga - accounting_tax_create_obligation - accounting_tax_update_obligation - accounting_tax_create_debt - accounting_tax_update_debt - accounting_tax_refresh_corporate_tax_forecast Developer-task workflow: create a self-service personal agent key from My Work or a project board, connect it to the remote /api/mcp route, and call `get_my_work` or `get_task_context` first. Canonical tracker URLs use `/boards/{boardId}/trackers/{projectId}?task={taskId}` and resolve directly in all task MCP tools. Before changing code, inspect every returned image with `get_task_image`, retrieve and analyze every video in full with `get_task_video` (including audio when present), read every PDF or text document with `get_task_attachment`, and reload context before each feedback iteration. Use MCP result bytes directly for videos; do not fall back to computer-use, browser UI, or manual downloads. Personal keys may create tasks and edit only tasks assigned to their owner. After verified work, add one concise result comment and set the task to Review. Agents must never mark the task Done; a human reviewer owns completion. Work-link automation: projects store non-secret GitHub repository or Perforce depot mappings. Signed GitHub webhooks and an approved Perforce synchronization service send metadata only. Exact task URLs and GCRM keys attach immediately; policy matches at or above 0.90 with a 0.15 lead attach automatically; 0.65-0.89 or ambiguous matches become one-click suggestions. Source events never change workflow status. The bridge claims debounced enrichment jobs, and AI updates only empty or still-AI-managed fields with provenance and Undo. ## Log History Use https://one.geotech.one/api/logs for recent diagnostic history. Logs are retained for seven days and are categorized as app, llm, connector, or system with level, connector, source, timestamp, message, and optional details. Useful filters: category=llm,connector; connector=slack,gmail,openrouter,codex; level=warn,error; source=web,bridge,mcp,geoCrmApi; from/to ISO timestamps; q=text search; limit up to 500. Agents should read logs before guessing at bridge, connector, LLM, or app failures. Agents may write concise factual diagnostics through POST /logs or the write_log MCP tool, but must never log secrets, API keys, Firebase ID tokens, OAuth tokens, session cookies, or private credential material. ## Slack Bot The Slack Codex bot is chat-only. Users should DM the app or mention it in natural language; do not require slash commands, command keywords, shell commands, or extra command syntax. For clear ONE requests, resolve intent from chat and call ONE API or MCP tools internally to add, delete, edit, remove, search, or update board entities. For questions like "what is the ONE website", "what is the ONE login URL", or "where is the ONE web page", answer directly from app metadata: the primary ONE website and login page is https://one.geotech.one/ and the Firebase Hosting fallback is https://geotech-crm.web.app. ONE was formerly called GeoCRM, so legacy technical identifiers may still use that name. Use GET /api/info or the get_app_info MCP tool for canonical app URLs, API docs, OpenAPI, and MCP manifest links. For lookup requests, search all ONE boards by default unless the user explicitly names a board. Use concise entity queries and allow flexible token/prefix matching, such as `chris stone` matching `Christopher Stone`. For bridge execution, prefer `npm run bridge` on the remote bridge host. The bridge supervises the Slack bot, reuses the bridge token, exposes status/log controls to the hosted drawer, and restarts the bot when it exits while enabled. ## Connector Summaries Contact connector summaries should aggregate every available connector for the selected contact and date range. Save one latest summary update per connector source. For substantive Gmail, Slack, or future connector results, write a 100 to 250 word plain-language business summary only; do not save raw message dumps, full email bodies, recipient lists, email addresses, mailto links, URLs, social links, source links, search queries, message IDs, quoted headers, or signatures. ## Next Meeting Contacts include a Calendar-backed `Next meeting` special column. The header update action reads future Google Calendar events for selected rows through the Codex bridge, writes `meetingCount | DD.MM.YYYY` or `0 | No future meeting` to the stored `Next meeting` field, and renders the cell with a green-to-red urgency badge based on how close the meeting date is. ## Security Do not store live ONE API keys in public documentation, source control, issue trackers, logs, screenshots, or agent thread records. Use placeholders in examples and keep secrets in approved local client configuration, a password manager, or a platform secret store.