# Squario developer documentation Release preview: REST API v1 is implemented on feat/main and awaits the production main release. Use the API base URL copied from workspace Settings > API; do not assume a production vanity host. OpenAPI 3.1: https://www.squar.io/docs/openapi.json ## Build on your workspace. https://www.squar.io/docs Connect your tools to Squario with a versioned JSON API. Discover the schema, read data and make changes with your app permissions. ### One API, your workspace The REST API uses HTTPS and JSON. API keys belong to one member in one workspace. Your base URL already ends in /functions/v1/public-api/v1; copy it from Settings → API and append the endpoint path used in these guides. The documentation lives at /docs, alongside the Squario website. - Authenticate with Authorization: Bearer . - Read a list in data with pagination information in meta. - Read or write one record in a data object. - Use X-Request-Id to trace a request. ### Permissions travel with the key Every operation acts as the member who created the key. Workspace membership, resource permissions and field restrictions are checked on the server. A key’s read/write access, resource allowlist and IP allowlist can narrow that access. They cannot expand it. ### REST API or MCP Both connections use the same resource action core. Choose REST for an integration that you control, or MCP to connect an AI client with the member’s consent. Connection | Credential | Best fit | Usage REST API | Member API key | Server integrations, imports and synchronisation | Monthly API request allowance MCP | OAuth 2.1 grant | Remote AI clients and assistants | Workspace AI credits ### Start with a read Make a request to /me, discover the resources your key covers, then describe the resource you need. Its live schema includes your workspace’s custom fields. The endpoint reference documents every route and its request and response schemas. - Your first API request: /docs/quickstart - API endpoint reference: /docs/api-reference - Connect an AI client with MCP: /docs/mcp ## Your first API request https://www.squar.io/docs/quickstart Create a scoped key, copy your base URL and verify the connection with cURL, JavaScript or Python. ### Prepare the connection In Squario, choose the workspace and open Settings → API → Keys. API access requires an eligible plan and the api.access permission. Owners and administrators have that permission by default. - Create a named key with a mandatory expiry, choosing the smallest access and resource scope your integration needs. - Copy the secret when it is shown. You cannot retrieve it later. - Copy the base URL from the connection details. Keep its /v1 suffix. - Store the key in your server’s secret manager or environment. Start with a read-only key. ```bash read -r -p 'API base URL from Settings → API: ' SQUARIO_API_BASE SQUARIO_API_BASE="${SQUARIO_API_BASE%/}" read -r -s -p 'API key: ' SQUARIO_API_KEY printf '\n' export SQUARIO_API_BASE SQUARIO_API_KEY ``` ### Check your identity These examples use SQUARIO_API_BASE for the copied base URL and SQUARIO_API_KEY for the secret. Set them in your local environment. /me returns your key’s metadata, workspace and member, plus current quota and rate-limit information. It never returns the secret. ```bash curl --fail-with-body "$SQUARIO_API_BASE/me" \ --header "Authorization: Bearer $SQUARIO_API_KEY" ``` ```javascript const base = process.env.SQUARIO_API_BASE?.replace(/\/$/, ""); const key = process.env.SQUARIO_API_KEY; if (!base || !key) throw new Error("Set SQUARIO_API_BASE and SQUARIO_API_KEY"); const response = await fetch(`${base}/me`, { headers: { Authorization: `Bearer ${key}` }, signal: AbortSignal.timeout(30_000), }); const body = await response.json(); if (!response.ok) { throw new Error(`${body.error.code}: ${body.error.message} (${body.error.request_id})`); } console.log(body.data); ``` ```python import json import os from urllib.request import Request, urlopen base = os.environ["SQUARIO_API_BASE"].rstrip("/") key = os.environ["SQUARIO_API_KEY"] request = Request(f"{base}/me", headers={"Authorization": f"Bearer {key}"}) with urlopen(request, timeout=30) as response: body = json.load(response) print(body["data"]) ``` ### Find a resource and its schema /resources returns catalog entries with key, label, read_only, searchable and requires_model_id. The catalog is filtered by the key’s resource allowlist; resource permissions are still checked when you access the data. Describe a resource before relying on its fields or writing records. ```bash curl --fail-with-body "$SQUARIO_API_BASE/resources" \ --header "Authorization: Bearer $SQUARIO_API_KEY" curl --fail-with-body "$SQUARIO_API_BASE/resources/companies" \ --header "Authorization: Bearer $SQUARIO_API_KEY" ``` ### Inspect the contract without a key The version root and /openapi.json are public. Use them to identify the API and fetch its OpenAPI 3.1 contract. These public calls do not consume your workspace’s request allowance. The copy in this documentation is a release snapshot; the deployed API’s document reflects its deployment. ```bash curl --fail-with-body "$SQUARIO_API_BASE" curl --fail-with-body "$SQUARIO_API_BASE/openapi.json" ``` - Download OpenAPI: /docs/openapi.json ### Make your integration reliable Continue with filters and pagination for reads, or safe writes for creation and updates. Read the error guide before adding retries. Use an Idempotency-Key for write retries and honour Retry-After. - Authentication and access: /docs/authentication - Querying and pagination: /docs/querying - Safe writes and retries: /docs/writes ## Authentication and access https://www.squar.io/docs/authentication Understand member keys, workspace boundaries, restrictions, expiration and safe rotation. ### Send a bearer key Authenticated endpoints accept Authorization: Bearer . Keys start with sqk_, followed by 64 hexadecimal characters. A key is bound to its owner and workspace; there is no workspace selector in the request. - Use the key on your server. This API does not send CORS headers. - Never put a key in client-side JavaScript, a URL, source control or a public log. - Use HTTPS and keep development and production keys separate. ### Scope the integration Choose restrictions when you create a key. They apply on top of its owner’s current permissions. Restriction | Behaviour Access | read or write (read and write). POST /query is a read operation. Resources | An explicit allowlist, or all catalog resources. Association operations require both sides. IP addresses | Optional IP/CIDR allowlist for your server’s outbound addresses. Expiry | Required. The app offers a lifetime of at most one year. ### Rotate and revoke The secret is shown once; Squario stores a hash. Create a replacement key, update your integration’s secret, verify it with /me, then revoke the old key in Settings → API. Name keys after the integration so usage and changes are easy to recognise. - Expired and revoked keys stop working. - Removing the owner’s API permission or changing the plan can stop an existing key immediately. - A membership becoming inactive revokes its keys. Reactivating the membership does not restore them. - Expiry reminders are scheduled 14 and 3 days before expiry, subject to the owner’s notification preferences and the key’s lifetime. ### When MFA changes A key delegates the sign-in assurance of the session that created it. If a newly verified MFA factor makes that assurance stale, requests return 401 key_assurance_stale. Sign in with fresh MFA and create a replacement key. ### API access and administration api.access permits members to create and use their own keys. api.manage permits administrators to view and revoke members’ keys and inspect workspace-wide usage. API access is available on Pro, Growth, Scale and Enterprise. Permissions and the plan are checked again on every request. - Limits, usage and observability: /docs/limits-and-observability - Errors and recovery: /docs/errors ## Resources and live schemas https://www.squar.io/docs/resources Discover the resource catalog, workspace fields, custom data models and the schema you can actually use. ### Discover instead of guessing Call /resources for the catalog available to your key, then /resources/{resource} for the workspace’s live field description and association catalog. The description includes the writable field schema, required fields, options and available keys for sorting and filtering. It is not a complete list of every readable or managed response field. A catalog entry is not a grant to read every record. - CRM resources include companies, contacts, deals, leads, products and activities. - Delivery resources include projects, project_tasks and the project reference catalogs. - Workspace vocabulary includes pipelines, stages, tags, departments and other resource-specific catalogs. - entity_members, automations and project_approvals are read-only. - The complete resource list and each supported operation appear in the endpoint reference. ```bash curl --fail-with-body "$SQUARIO_API_BASE/resources" \ --header "Authorization: Bearer $SQUARIO_API_KEY" curl --fail-with-body "$SQUARIO_API_BASE/resources/companies" \ --header "Authorization: Bearer $SQUARIO_API_KEY" ``` ### Use the workspace’s field keys Custom fields and option values vary by workspace. Read the description before building a payload. Filtering a custom field uses its filter_key, usually cfv:; writing uses cf__ or a custom_fields object keyed by the field key. Those are different identifiers. Formula fields and other read-only fields cannot be written. ### Custom data model records data_model_records exposes records inside a custom data model, including form-backed models. Get the model UUID from the app’s model settings or through the MCP list_data_models tool. There is no REST /data_models discovery endpoint. - Supply model_id to describe or list model records, including POST /query. - Supply model_id when creating or updating a model record, in the flat body or query string. - The live model schema determines its editable and required fields. - Keep the model identifier with your integration configuration; do not guess it from a record identifier. ```bash read -r -p 'Data model id from Squario: ' MODEL_ID curl --fail-with-body --get "$SQUARIO_API_BASE/data_model_records" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --data-urlencode "model_id=$MODEL_ID" \ --data-urlencode 'page_size=25' curl --fail-with-body --get "$SQUARIO_API_BASE/resources/data_model_records" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --data-urlencode "model_id=$MODEL_ID" ``` ### Select fields without bypassing permissions Use fields=name,domain on a list or a record GET, or fields: ["name", "domain"] in a query body. id is kept. Names absent from the returned record are skipped. Field selection reduces the response size; it does not reduce database query work. Restricted fields remain masked or absent according to the resource projection. ### A contract that follows your configuration Use the OpenAPI reference for routes and transport schemas, and the authenticated description for live workspace fields. The static reference cannot know your custom fields or every role’s current permissions. - API endpoint reference: /docs/api-reference - Associations between records: /docs/associations ## Querying and pagination https://www.squar.io/docs/querying Filter, sort, search and page through records, with cursor pagination for integrations that need to go deeper. ### GET a list or POST a query GET /{resource} and POST /{resource}/query use the same read path. GET encodes filters in the singular filter query parameter; POST uses a filters array in its JSON body. POST /query works with a read-only key. Unknown or repeated query parameters return 400 invalid_request. Parameter | Meaning page / cursor | Choose one pagination mode. Page defaults to 1; start a cursor walk with start. page_size | 1–100 records; default 25. sort / order | A sortable field key, and asc or desc. Default order is newest first. search | Free-text search on resources with searchable: true; ranks a bounded 500-candidate window. include_archived | Include archived records; false by default. filter / filters, join | Structured filters, combined with and (default) or or. fields | Comma-separated names in GET; an array in POST /query. model_id | Required for data_model_records; does not apply to other resources. ### Use certified filters Each filter has field, op and, when needed, value. Fields, operators and values are checked against the workspace’s capabilities. A native field uses its field key; custom fields use the described filter_key; related fields use rel:.. Operators | Value eq, ne, gt, gte, lt, lte | A compatible scalar. iLike, notILike | Case-insensitive text matching. inArray, notInArray | An array of compatible values. isBetween | A two-value range. isEmpty, isNotEmpty | No value needed. ```bash curl --fail-with-body --request POST "$SQUARIO_API_BASE/companies/query" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header 'Content-Type: application/json' \ --data '{ "filters": [{ "field": "name", "op": "iLike", "value": "Northfold" }], "join": "and", "page_size": 25, "fields": ["name"] }' ``` ```bash curl --fail-with-body --get "$SQUARIO_API_BASE/companies" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --data-urlencode 'filter=[{"field":"name","op":"iLike","value":"Northfold"}]' \ --data-urlencode 'fields=name' \ --data-urlencode 'page_size=25' ``` ### Read the pagination metadata A list returns data and meta. Page mode includes page, page_size, total and has_more. total_is_capped: true means total is a lower bound. Page numbers address an offset window through 10,000; requests past the permitted page return 400 with details.max_page. For exports and deep synchronisation, use cursors. ```json { "data": [{ "id": "c91b7028-f985-4bc1-9f75-c76533c3133a", "name": "Northfold" }], "meta": { "page": 1, "page_size": 25, "total": 1, "has_more": false } } ``` ### Walk with an opaque cursor Send cursor=start, then send the response’s meta.next_cursor unchanged until it is null. Do not also send page. Keep filters, sort and other query settings stable throughout the walk. A cursor is a position, not a snapshot of a changing workspace. - Cursor responses carry page_size, next_cursor, cursor_supported, total and has_more. - Free-text relevance sorting cannot be walked; cursor_supported is false on its first page. Use page mode for that query. - A positioned cursor that does not match the query returns 400. Restart the walk after changing the sort or filters. - Treat cursors as opaque. Do not decode, edit or manufacture them. ```javascript const base = process.env.SQUARIO_API_BASE?.replace(/\/$/, ""); const key = process.env.SQUARIO_API_KEY; if (!base || !key) throw new Error("Set SQUARIO_API_BASE and SQUARIO_API_KEY"); let cursor = "start"; while (cursor !== null) { const url = new URL(`${base}/companies`); url.searchParams.set("cursor", cursor); url.searchParams.set("page_size", "100"); url.searchParams.set("fields", "name"); const response = await fetch(url, { headers: { Authorization: `Bearer ${key}` }, signal: AbortSignal.timeout(30_000), }); const body = await response.json(); if (!response.ok) throw new Error(`${body.error.code} (${body.error.request_id})`); if (!body.meta.cursor_supported) throw new Error("Use page mode for this sort"); for (const record of body.data) console.log(record.id, record.name); cursor = body.meta.next_cursor; } ``` - Errors and recovery: /docs/errors - Limits, usage and observability: /docs/limits-and-observability ## Safe writes and retries https://www.squar.io/docs/writes Create, patch, archive and restore records, with exact payloads and idempotency for repeatable requests. ### Send a flat record payload Create with POST /{resource} and update with PATCH /{resource}/{id}. Send the field values directly in a JSON object, not inside a fields wrapper. PATCH changes only the fields you supply. Describe the resource first to discover required fields and valid options. The examples use a company named Northfold; workspace-specific required fields may need to be added. - Create returns 201, { data: record } and a Location header. - Update returns 200 and { data: record }. - Unknown fields and invalid values are refused, rather than silently accepted. - Writes need a write key and the owner’s resource and field write permissions. ```bash # Set IDEMPOTENCY_KEY once for this logical operation; keep it for retries. read -r -p 'Unique operation key: ' IDEMPOTENCY_KEY curl --fail-with-body --include --request POST "$SQUARIO_API_BASE/companies" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: $IDEMPOTENCY_KEY" \ --data '{"name":"Northfold"}' ``` ```bash # Use the actual id returned by creation and a new key for this operation. read -r -p 'Company id: ' COMPANY_ID read -r -p 'Unique update operation key: ' UPDATE_KEY curl --fail-with-body --request PATCH "$SQUARIO_API_BASE/companies/$COMPANY_ID" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: $UPDATE_KEY" \ --data '{"name":"Northfold Studio"}' ``` ### Write custom fields by key Use either flat cf__ properties or one custom_fields object. Do not mix both formats in a request. Replace integration_code in the example with a real editable field key from your workspace’s schema. Required and conditional field rules are enforced on the server. ```json { "custom_fields": { "integration_code": "northfold-001" } } ``` ### Archive instead of deleting permanently DELETE /{resource}/{id} archives the record. It is a soft delete; you may send { reason } as an optional JSON body. Restore with POST /{resource}/{id}/restore. Both return the resulting record in data. Active lists exclude archived records unless you set include_archived=true. ```bash read -r -p 'Unique archive operation key: ' ARCHIVE_KEY curl --fail-with-body --request DELETE "$SQUARIO_API_BASE/companies/$COMPANY_ID" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: $ARCHIVE_KEY" \ --data '{"reason":"Integration cleanup"}' read -r -p 'Unique restore operation key: ' RESTORE_KEY curl --fail-with-body --request POST "$SQUARIO_API_BASE/companies/$COMPANY_ID/restore" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header "Idempotency-Key: $RESTORE_KEY" ``` ### Make write retries deliberate Every record write and association PUT/DELETE accepts Idempotency-Key. Generate one unique key per logical operation, store it with the operation, and reuse it for retries. It must contain 1–255 printable ASCII characters without spaces and is scoped to the API key. The fingerprint includes method, /v1 path, query string and exact body bytes. Situation | Result First request | The write runs; a successful response is retained for 24 hours. Same request, completed | The original success is replayed with current visibility and field masks; Idempotent-Replayed: true. Same request, running | 409 idempotency_key_in_use; Retry-After: 1. Same key, different request | 422 idempotency_key_reused. Use a new key for a different operation. ### Plan for an uncertain outcome Idempotency reduces duplicate writes, but it is not an exactly-once guarantee. An unfinished claim can be taken over after five minutes; a write that committed just before a worker failed can run again. After an ambiguous failure, retry with the original key and bytes, then reconcile the record before creating a new operation. Reads ignore this header, and only successful responses are stored. - Associations between records: /docs/associations - Errors and recovery: /docs/errors ## Associations between records https://www.squar.io/docs/associations Link companies, contacts, deals, projects and tags using the same relationship rules as the app. ### Discover the other side An association is named after the target resource. Read /resources/{resource} and inspect associations before building a relationship. The key’s resource allowlist must include both the source and the target, and its owner must be allowed to access both records. Resources | Direction | Link fields companies / contacts | Both directions | Employment role, flags, dates and notes. deals / contacts | Both directions | role, is_primary. projects / deals | Both directions | No editable link fields. Companies, contacts, deals, leads, activities, products → tags | Toward tags only | No editable link fields; use a tag_ids filter for the reverse lookup. ### Read, link and unlink GET /{resource}/{id}/{association} lists links. PUT /{resource}/{id}/{association}/{target_id} creates or updates a link, with an optional object of link fields. Creation returns 201; an existing link returns 200. DELETE on the same target path removes the link, takes no body, and returns 404 if it did not exist. PUT and DELETE support Idempotency-Key. ```bash read -r -p 'Company id: ' COMPANY_ID read -r -p 'Contact id: ' CONTACT_ID read -r -p 'Unique link operation key: ' LINK_KEY curl --fail-with-body --request PUT "$SQUARIO_API_BASE/companies/$COMPANY_ID/contacts/$CONTACT_ID" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: $LINK_KEY" \ --data '{"job_title":"Operations lead","is_primary":true}' ``` ```bash curl --fail-with-body "$SQUARIO_API_BASE/companies/$COMPANY_ID/contacts" \ --header "Authorization: Bearer $SQUARIO_API_KEY" read -r -p 'Unique unlink operation key: ' UNLINK_KEY curl --fail-with-body --request DELETE "$SQUARIO_API_BASE/companies/$COMPANY_ID/contacts/$CONTACT_ID" \ --header "Authorization: Bearer $SQUARIO_API_KEY" \ --header "Idempotency-Key: $UNLINK_KEY" ``` ### Employment has its own rules Company/contact links accept job_title, department, role_label, role_description, decision_power, buying_role, is_primary, is_decision_maker, is_billing_contact, is_technical_contact, started_at and notes. Consult the reference for their types and options. - A new link defaults to is_primary: false. Making it primary demotes the contact’s previous primary company. - Omitting is_primary on an existing link preserves its value. - DELETE ends the employment with today’s date and clears its primary flag. Ended links disappear from the association list. - Deleting a project’s primary deal link returns 409; change that primary relationship in the app first. ### Understand a link response Each link exposes the two record identifiers, its allowed link fields and timestamps, without the link table’s own identifier, author or internal metadata. List responses include data and meta: { page, page_size, has_more }, ordered oldest first, with no total count. Link pages default to 100 and accept 1–100. Withheld link fields are null, including boolean flags; a boolean PUT field still requires a boolean. - API endpoint reference: /docs/api-reference - Safe writes and retries: /docs/writes ## Errors and recovery https://www.squar.io/docs/errors Use stable error codes, structured details and request identifiers to decide what to fix and when to retry. ### A consistent error envelope Errors use an error object with type, code, message, request_id and optional details. Branch on the HTTP status and stable code; treat the message as diagnostic text. Every response also has X-Request-Id. Keep that identifier when reporting a problem, while keeping keys and sensitive record payloads out of logs. ```json { "error": { "type": "validation_error", "code": "validation_failed", "message": "The supplied field is not available.", "details": { "unknown": ["nname"], "nearest": { "nname": ["name"] } }, "request_id": "4d85a25f-d510-41f5-b228-32a875670fd0" } } ``` ### Choose the right recovery Fix invalid input and access problems before retrying. A 404 also covers a record in another workspace or a record the owner cannot see. Status | Codes | Recovery 400 | invalid_request | Fix JSON, parameters, filters or cursor settings. 401 | invalid_api_key, expired_api_key, key_assurance_stale | Check the secret, expiry and MFA; replace the key when needed. 403 | ip_not_allowed, permission_denied, plan_upgrade_required, insufficient_scope, feature_unavailable, forbidden | Check server IP, membership, role, plan, key scope and workspace availability. 404 | not_found, unknown_resource, route_not_found | Check the path, identifiers and the owner’s visibility. 405 | method_not_allowed | Use a supported verb from the Allow header; some resources are read-only. 409 | conflict, idempotency_key_in_use | Resolve the conflict, or wait before retrying the same idempotent request. 413 | payload_too_large | Reduce the request body to at most 1 MiB. 422 | validation_failed, idempotency_key_reused | Correct fields/types or use a new key for a different operation. 429 | rate_limited, quota_exceeded | Honour Retry-After; inspect limits and the quota reset. 500 / 503 | internal_error, service_unavailable | Retry with bounded backoff; preserve the write’s idempotency key. ### Use the details, not guesswork Validation details can include unknown, nearest and alternatives, naming fields or options to correct. Pagination errors can include max_page; quota errors can include resets_at; database validation can include sqlstate and a relevant hint. Describe the resource again if the workspace schema has changed. ### Retry with limits For transient failures, use a bounded number of retries with exponential backoff and jitter. Respect Retry-After when present. Do not automatically retry a 400, 401, 403 or validation failure. Preserve the exact request and idempotency key across write retries, and reconcile uncertain outcomes before issuing a new write. - Safe writes and retries: /docs/writes - Limits, usage and observability: /docs/limits-and-observability ## Limits, usage and observability https://www.squar.io/docs/limits-and-observability Read the quota and rate-limit headers, monitor usage, and trace API changes in Squario. ### Monthly request allowances The request allowance is shared by the workspace and resets monthly in UTC. Consult /me, response headers and Settings → API → Usage for the effective limits, including any workspace overrides. Plan | Monthly requests Free | API access unavailable Pro | 50,000 Growth | 250,000 Scale | 1,000,000 Enterprise | Unlimited by default ### Pace requests across your workers Default limits are 120 requests/minute and 5,000/hour per key, plus 600/minute per workspace. Limits can be configured by the operator. Sharing load across keys does not bypass the workspace limit. Invalid keys have a separate IP-based abuse budget. - X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset describe the tightest enabled bucket. - X-RateLimit-Reset is seconds until that window resets, not a Unix timestamp. - X-Quota-Limit, X-Quota-Remaining and X-Quota-Reset describe the monthly allowance. The reset is an ISO timestamp. - Unlimited quotas omit the limit and remaining headers. Rate headers are omitted when all rate buckets are disabled. - 429 responses provide Retry-After. Use it rather than busy-polling. ### What counts as a request An admitted authenticated request counts, including one whose handler later rejects invalid input, an idempotent replay or a failure. Admission refusals for invalid keys, permissions, scopes, rate limits and quota do not count. A release-gate refusal happens after admission and does count. Public metadata and OpenAPI calls do not count. Concurrent requests can slightly exceed the monthly boundary; do not build around that overshoot. ### Inspect usage and changes Settings → API contains Keys, Usage and Request log. Inspect request identifiers, methods, paths, statuses and timings; request-log entries are retained for 14 days. Members see their own key activity, while administrators with api.manage can inspect workspace-wide activity. - API writes appear in the workspace audit trail as API · , attributed to the key’s owner. - Keep X-Request-Id in your own operational logs, without logging the bearer secret. - Raw request-log paths and timing help diagnose a call; audit entries explain the actual record changes. ### Send changes to another system There is no REST webhook-subscription endpoint. Configure a record-triggered automation with a webhook action in Squario to notify your HTTPS receiver. The receiver can use this API to fetch the records it needs. Follow the automation’s configuration for the outgoing payload and credentials. - Errors and recovery: /docs/errors - Connect an AI client with MCP: /docs/mcp ## Connect an AI client with MCP https://www.squar.io/docs/mcp Grant an AI client access to a workspace using OAuth, with the same resource permissions as its member. ### Copy the connector URL In Squario, open Account → Connected apps and copy the MCP server URL. Add it as a remote or custom MCP server in a client that supports remote OAuth servers. The URL ends in /functions/v1/mcp-server/mcp; it is different from the REST API base URL. Use the URL shown in the app. - The client discovers the server, registers itself and opens the consent screen. - Sign in, choose the workspace and approve the grant. - The client receives OAuth tokens and discovers the available tools. - Revoke the connection from Account → Connected apps at any time. ### A grant acts as you MCP uses OAuth 2.1 with PKCE, not a member API key. Its tokens bind one member to one workspace. Membership, squaria.mcp, record visibility and field permissions are rechecked on each call. Access tokens last one hour; refresh tokens last 30 days and rotate on use. The client should manage that lifecycle. ### Discover, validate, then write Start with describe_resource or describe_capabilities, then read the records you need. Use validate_change before a write. Tools are parameterised by resource and certified against the workspace’s schema. Purpose | Examples Records | list_records, get_record, resolve_reference, global_search Discovery | describe_resource, describe_capabilities, list_data_models, list_custom_fields Changes | validate_change, create_record, update_record, archive_record, restore_record Workspace context | list_forms, list_drive_items, list_audit_log, knowledge tools Views and reports | list_views, save_view, save_structural_view, run_report ### Approval, credits and limits Use your client’s tool-approval controls for writes. MCP calls spend workspace AI credits rather than the REST request allowance; a failed tool call is refunded. A repeated invocation is a new call and a new charge. Default tool limits are 60/minute and 1,000/hour per member and workspace. A throttled request returns 429 with Retry-After. - Drive tools expose metadata, never file contents. - MCP does not expose the in-app page navigation and detail-layout actions. - Available tools can change with the server release. Use the client’s tool discovery as the contract. - Resources and live schemas: /docs/resources - Authentication and access: /docs/authentication ## API endpoint reference https://www.squar.io/docs/api-reference Explore every resource, endpoint, parameter and request/response schema from the API’s OpenAPI 3.1 contract. ### Generated from the implementation The reference is generated from Squario’s public API resource and association catalogs. Select a resource to see its operations and schemas. Technical contract descriptions remain in English; paths, fields and error codes are language-independent. For current workspace-specific custom fields, call /resources/{resource} with your key. - Download OpenAPI: /docs/openapi.json ### Base URL and version In these guides, SQUARIO_API_BASE is the URL copied from Settings → API, including /v1. In OpenAPI, the server URL stops at /functions/v1/public-api because its paths already include /v1. Supply your actual server URL when importing the downloadable release snapshot into a client. Public GET /v1 and GET /v1/openapi.json need no key; all data endpoints use bearer authentication. ## Endpoint index GET /v1 — API root GET /v1/openapi.json — This document GET /v1/me — The key, its workspace and its current usage GET /v1/resources — The resources this key can use GET /v1/resources/{resource} — A resource's fields in this workspace, custom fields included GET /v1/companies — List companies POST /v1/companies — Create one of companies POST /v1/companies/query — List companies, parameters in the body GET /v1/companies/{id} — Get one of companies PATCH /v1/companies/{id} — Update one of companies DELETE /v1/companies/{id} — Archive one of companies POST /v1/companies/{id}/restore — Restore an archived one of companies GET /v1/companies/{id}/contacts — List the contacts linked to one of companies PUT /v1/companies/{id}/contacts/{target_id} — Link one of contacts to one of companies, or update the link DELETE /v1/companies/{id}/contacts/{target_id} — Unlink one of contacts from one of companies GET /v1/companies/{id}/tags — List the tags linked to one of companies PUT /v1/companies/{id}/tags/{target_id} — Link one of tags to one of companies, or update the link DELETE /v1/companies/{id}/tags/{target_id} — Unlink one of tags from one of companies GET /v1/contacts — List contacts POST /v1/contacts — Create one of contacts POST /v1/contacts/query — List contacts, parameters in the body GET /v1/contacts/{id} — Get one of contacts PATCH /v1/contacts/{id} — Update one of contacts DELETE /v1/contacts/{id} — Archive one of contacts POST /v1/contacts/{id}/restore — Restore an archived one of contacts GET /v1/contacts/{id}/companies — List the companies linked to one of contacts PUT /v1/contacts/{id}/companies/{target_id} — Link one of companies to one of contacts, or update the link DELETE /v1/contacts/{id}/companies/{target_id} — Unlink one of companies from one of contacts GET /v1/contacts/{id}/deals — List the deals linked to one of contacts PUT /v1/contacts/{id}/deals/{target_id} — Link one of deals to one of contacts, or update the link DELETE /v1/contacts/{id}/deals/{target_id} — Unlink one of deals from one of contacts GET /v1/contacts/{id}/tags — List the tags linked to one of contacts PUT /v1/contacts/{id}/tags/{target_id} — Link one of tags to one of contacts, or update the link DELETE /v1/contacts/{id}/tags/{target_id} — Unlink one of tags from one of contacts GET /v1/deals — List deals POST /v1/deals — Create one of deals POST /v1/deals/query — List deals, parameters in the body GET /v1/deals/{id} — Get one of deals PATCH /v1/deals/{id} — Update one of deals DELETE /v1/deals/{id} — Archive one of deals POST /v1/deals/{id}/restore — Restore an archived one of deals GET /v1/deals/{id}/contacts — List the contacts linked to one of deals PUT /v1/deals/{id}/contacts/{target_id} — Link one of contacts to one of deals, or update the link DELETE /v1/deals/{id}/contacts/{target_id} — Unlink one of contacts from one of deals GET /v1/deals/{id}/projects — List the projects linked to one of deals PUT /v1/deals/{id}/projects/{target_id} — Link one of projects to one of deals, or update the link DELETE /v1/deals/{id}/projects/{target_id} — Unlink one of projects from one of deals GET /v1/deals/{id}/tags — List the tags linked to one of deals PUT /v1/deals/{id}/tags/{target_id} — Link one of tags to one of deals, or update the link DELETE /v1/deals/{id}/tags/{target_id} — Unlink one of tags from one of deals GET /v1/leads — List leads POST /v1/leads — Create one of leads POST /v1/leads/query — List leads, parameters in the body GET /v1/leads/{id} — Get one of leads PATCH /v1/leads/{id} — Update one of leads DELETE /v1/leads/{id} — Archive one of leads POST /v1/leads/{id}/restore — Restore an archived one of leads GET /v1/leads/{id}/tags — List the tags linked to one of leads PUT /v1/leads/{id}/tags/{target_id} — Link one of tags to one of leads, or update the link DELETE /v1/leads/{id}/tags/{target_id} — Unlink one of tags from one of leads GET /v1/products — List products POST /v1/products — Create one of products POST /v1/products/query — List products, parameters in the body GET /v1/products/{id} — Get one of products PATCH /v1/products/{id} — Update one of products DELETE /v1/products/{id} — Archive one of products POST /v1/products/{id}/restore — Restore an archived one of products GET /v1/products/{id}/tags — List the tags linked to one of products PUT /v1/products/{id}/tags/{target_id} — Link one of tags to one of products, or update the link DELETE /v1/products/{id}/tags/{target_id} — Unlink one of tags from one of products GET /v1/activities — List activities POST /v1/activities — Create one of activities POST /v1/activities/query — List activities, parameters in the body GET /v1/activities/{id} — Get one of activities PATCH /v1/activities/{id} — Update one of activities DELETE /v1/activities/{id} — Archive one of activities POST /v1/activities/{id}/restore — Restore an archived one of activities GET /v1/activities/{id}/tags — List the tags linked to one of activities PUT /v1/activities/{id}/tags/{target_id} — Link one of tags to one of activities, or update the link DELETE /v1/activities/{id}/tags/{target_id} — Unlink one of tags from one of activities GET /v1/locations — List locations POST /v1/locations — Create one of locations POST /v1/locations/query — List locations, parameters in the body GET /v1/locations/{id} — Get one of locations PATCH /v1/locations/{id} — Update one of locations DELETE /v1/locations/{id} — Archive one of locations POST /v1/locations/{id}/restore — Restore an archived one of locations GET /v1/testimonials — List testimonials POST /v1/testimonials — Create one of testimonials POST /v1/testimonials/query — List testimonials, parameters in the body GET /v1/testimonials/{id} — Get one of testimonials PATCH /v1/testimonials/{id} — Update one of testimonials DELETE /v1/testimonials/{id} — Archive one of testimonials POST /v1/testimonials/{id}/restore — Restore an archived one of testimonials GET /v1/pipelines — List pipelines POST /v1/pipelines — Create one of pipelines POST /v1/pipelines/query — List pipelines, parameters in the body GET /v1/pipelines/{id} — Get one of pipelines PATCH /v1/pipelines/{id} — Update one of pipelines DELETE /v1/pipelines/{id} — Archive one of pipelines POST /v1/pipelines/{id}/restore — Restore an archived one of pipelines GET /v1/pipeline_stages — List pipeline_stages POST /v1/pipeline_stages — Create one of pipeline_stages POST /v1/pipeline_stages/query — List pipeline_stages, parameters in the body GET /v1/pipeline_stages/{id} — Get one of pipeline_stages PATCH /v1/pipeline_stages/{id} — Update one of pipeline_stages DELETE /v1/pipeline_stages/{id} — Archive one of pipeline_stages POST /v1/pipeline_stages/{id}/restore — Restore an archived one of pipeline_stages GET /v1/product_categories — List product_categories POST /v1/product_categories — Create one of product_categories POST /v1/product_categories/query — List product_categories, parameters in the body GET /v1/product_categories/{id} — Get one of product_categories PATCH /v1/product_categories/{id} — Update one of product_categories DELETE /v1/product_categories/{id} — Archive one of product_categories POST /v1/product_categories/{id}/restore — Restore an archived one of product_categories GET /v1/tax_classes — List tax_classes POST /v1/tax_classes — Create one of tax_classes POST /v1/tax_classes/query — List tax_classes, parameters in the body GET /v1/tax_classes/{id} — Get one of tax_classes PATCH /v1/tax_classes/{id} — Update one of tax_classes DELETE /v1/tax_classes/{id} — Archive one of tax_classes POST /v1/tax_classes/{id}/restore — Restore an archived one of tax_classes GET /v1/loss_reasons — List loss_reasons POST /v1/loss_reasons — Create one of loss_reasons POST /v1/loss_reasons/query — List loss_reasons, parameters in the body GET /v1/loss_reasons/{id} — Get one of loss_reasons PATCH /v1/loss_reasons/{id} — Update one of loss_reasons DELETE /v1/loss_reasons/{id} — Archive one of loss_reasons POST /v1/loss_reasons/{id}/restore — Restore an archived one of loss_reasons GET /v1/deal_sources — List deal_sources POST /v1/deal_sources — Create one of deal_sources POST /v1/deal_sources/query — List deal_sources, parameters in the body GET /v1/deal_sources/{id} — Get one of deal_sources PATCH /v1/deal_sources/{id} — Update one of deal_sources DELETE /v1/deal_sources/{id} — Archive one of deal_sources POST /v1/deal_sources/{id}/restore — Restore an archived one of deal_sources GET /v1/deal_role_types — List deal_role_types POST /v1/deal_role_types — Create one of deal_role_types POST /v1/deal_role_types/query — List deal_role_types, parameters in the body GET /v1/deal_role_types/{id} — Get one of deal_role_types PATCH /v1/deal_role_types/{id} — Update one of deal_role_types DELETE /v1/deal_role_types/{id} — Archive one of deal_role_types POST /v1/deal_role_types/{id}/restore — Restore an archived one of deal_role_types GET /v1/activity_type_definitions — List activity_type_definitions POST /v1/activity_type_definitions — Create one of activity_type_definitions POST /v1/activity_type_definitions/query — List activity_type_definitions, parameters in the body GET /v1/activity_type_definitions/{id} — Get one of activity_type_definitions PATCH /v1/activity_type_definitions/{id} — Update one of activity_type_definitions DELETE /v1/activity_type_definitions/{id} — Archive one of activity_type_definitions POST /v1/activity_type_definitions/{id}/restore — Restore an archived one of activity_type_definitions GET /v1/activity_outcome_definitions — List activity_outcome_definitions POST /v1/activity_outcome_definitions — Create one of activity_outcome_definitions POST /v1/activity_outcome_definitions/query — List activity_outcome_definitions, parameters in the body GET /v1/activity_outcome_definitions/{id} — Get one of activity_outcome_definitions PATCH /v1/activity_outcome_definitions/{id} — Update one of activity_outcome_definitions DELETE /v1/activity_outcome_definitions/{id} — Archive one of activity_outcome_definitions POST /v1/activity_outcome_definitions/{id}/restore — Restore an archived one of activity_outcome_definitions GET /v1/activity_templates — List activity_templates POST /v1/activity_templates — Create one of activity_templates POST /v1/activity_templates/query — List activity_templates, parameters in the body GET /v1/activity_templates/{id} — Get one of activity_templates PATCH /v1/activity_templates/{id} — Update one of activity_templates DELETE /v1/activity_templates/{id} — Archive one of activity_templates POST /v1/activity_templates/{id}/restore — Restore an archived one of activity_templates GET /v1/forecast_categories — List forecast_categories POST /v1/forecast_categories — Create one of forecast_categories POST /v1/forecast_categories/query — List forecast_categories, parameters in the body GET /v1/forecast_categories/{id} — Get one of forecast_categories PATCH /v1/forecast_categories/{id} — Update one of forecast_categories DELETE /v1/forecast_categories/{id} — Archive one of forecast_categories POST /v1/forecast_categories/{id}/restore — Restore an archived one of forecast_categories GET /v1/lead_disqualification_reasons — List lead_disqualification_reasons POST /v1/lead_disqualification_reasons — Create one of lead_disqualification_reasons POST /v1/lead_disqualification_reasons/query — List lead_disqualification_reasons, parameters in the body GET /v1/lead_disqualification_reasons/{id} — Get one of lead_disqualification_reasons PATCH /v1/lead_disqualification_reasons/{id} — Update one of lead_disqualification_reasons DELETE /v1/lead_disqualification_reasons/{id} — Archive one of lead_disqualification_reasons POST /v1/lead_disqualification_reasons/{id}/restore — Restore an archived one of lead_disqualification_reasons GET /v1/competitors — List competitors POST /v1/competitors — Create one of competitors POST /v1/competitors/query — List competitors, parameters in the body GET /v1/competitors/{id} — Get one of competitors PATCH /v1/competitors/{id} — Update one of competitors DELETE /v1/competitors/{id} — Archive one of competitors POST /v1/competitors/{id}/restore — Restore an archived one of competitors GET /v1/tags — List tags POST /v1/tags — Create one of tags POST /v1/tags/query — List tags, parameters in the body GET /v1/tags/{id} — Get one of tags PATCH /v1/tags/{id} — Update one of tags DELETE /v1/tags/{id} — Archive one of tags POST /v1/tags/{id}/restore — Restore an archived one of tags GET /v1/entity_members — List entity_members POST /v1/entity_members/query — List entity_members, parameters in the body GET /v1/entity_members/{id} — Get one of entity_members GET /v1/entity_departments — List entity_departments POST /v1/entity_departments — Create one of entity_departments POST /v1/entity_departments/query — List entity_departments, parameters in the body GET /v1/entity_departments/{id} — Get one of entity_departments PATCH /v1/entity_departments/{id} — Update one of entity_departments DELETE /v1/entity_departments/{id} — Archive one of entity_departments POST /v1/entity_departments/{id}/restore — Restore an archived one of entity_departments GET /v1/entity_job_titles — List entity_job_titles POST /v1/entity_job_titles — Create one of entity_job_titles POST /v1/entity_job_titles/query — List entity_job_titles, parameters in the body GET /v1/entity_job_titles/{id} — Get one of entity_job_titles PATCH /v1/entity_job_titles/{id} — Update one of entity_job_titles DELETE /v1/entity_job_titles/{id} — Archive one of entity_job_titles POST /v1/entity_job_titles/{id}/restore — Restore an archived one of entity_job_titles GET /v1/scope_documents — List scope_documents POST /v1/scope_documents — Create one of scope_documents POST /v1/scope_documents/query — List scope_documents, parameters in the body GET /v1/scope_documents/{id} — Get one of scope_documents PATCH /v1/scope_documents/{id} — Update one of scope_documents DELETE /v1/scope_documents/{id} — Archive one of scope_documents POST /v1/scope_documents/{id}/restore — Restore an archived one of scope_documents GET /v1/dashboards — List dashboards POST /v1/dashboards — Create one of dashboards POST /v1/dashboards/query — List dashboards, parameters in the body GET /v1/dashboards/{id} — Get one of dashboards PATCH /v1/dashboards/{id} — Update one of dashboards DELETE /v1/dashboards/{id} — Archive one of dashboards POST /v1/dashboards/{id}/restore — Restore an archived one of dashboards GET /v1/automations — List automations POST /v1/automations/query — List automations, parameters in the body GET /v1/automations/{id} — Get one of automations GET /v1/data_model_records — List data_model_records POST /v1/data_model_records — Create one of data_model_records POST /v1/data_model_records/query — List data_model_records, parameters in the body GET /v1/data_model_records/{id} — Get one of data_model_records PATCH /v1/data_model_records/{id} — Update one of data_model_records DELETE /v1/data_model_records/{id} — Archive one of data_model_records POST /v1/data_model_records/{id}/restore — Restore an archived one of data_model_records GET /v1/projects — List projects POST /v1/projects — Create one of projects POST /v1/projects/query — List projects, parameters in the body GET /v1/projects/{id} — Get one of projects PATCH /v1/projects/{id} — Update one of projects DELETE /v1/projects/{id} — Archive one of projects POST /v1/projects/{id}/restore — Restore an archived one of projects GET /v1/projects/{id}/deals — List the deals linked to one of projects PUT /v1/projects/{id}/deals/{target_id} — Link one of deals to one of projects, or update the link DELETE /v1/projects/{id}/deals/{target_id} — Unlink one of deals from one of projects GET /v1/project_tasks — List project_tasks POST /v1/project_tasks — Create one of project_tasks POST /v1/project_tasks/query — List project_tasks, parameters in the body GET /v1/project_tasks/{id} — Get one of project_tasks PATCH /v1/project_tasks/{id} — Update one of project_tasks DELETE /v1/project_tasks/{id} — Archive one of project_tasks POST /v1/project_tasks/{id}/restore — Restore an archived one of project_tasks GET /v1/project_deliverables — List project_deliverables POST /v1/project_deliverables — Create one of project_deliverables POST /v1/project_deliverables/query — List project_deliverables, parameters in the body GET /v1/project_deliverables/{id} — Get one of project_deliverables PATCH /v1/project_deliverables/{id} — Update one of project_deliverables DELETE /v1/project_deliverables/{id} — Archive one of project_deliverables POST /v1/project_deliverables/{id}/restore — Restore an archived one of project_deliverables GET /v1/project_signals — List project_signals POST /v1/project_signals — Create one of project_signals POST /v1/project_signals/query — List project_signals, parameters in the body GET /v1/project_signals/{id} — Get one of project_signals PATCH /v1/project_signals/{id} — Update one of project_signals DELETE /v1/project_signals/{id} — Archive one of project_signals POST /v1/project_signals/{id}/restore — Restore an archived one of project_signals GET /v1/project_approvals — List project_approvals POST /v1/project_approvals/query — List project_approvals, parameters in the body GET /v1/project_approvals/{id} — Get one of project_approvals GET /v1/project_statuses — List project_statuses POST /v1/project_statuses — Create one of project_statuses POST /v1/project_statuses/query — List project_statuses, parameters in the body GET /v1/project_statuses/{id} — Get one of project_statuses PATCH /v1/project_statuses/{id} — Update one of project_statuses DELETE /v1/project_statuses/{id} — Archive one of project_statuses POST /v1/project_statuses/{id}/restore — Restore an archived one of project_statuses GET /v1/project_task_statuses — List project_task_statuses POST /v1/project_task_statuses — Create one of project_task_statuses POST /v1/project_task_statuses/query — List project_task_statuses, parameters in the body GET /v1/project_task_statuses/{id} — Get one of project_task_statuses PATCH /v1/project_task_statuses/{id} — Update one of project_task_statuses DELETE /v1/project_task_statuses/{id} — Archive one of project_task_statuses POST /v1/project_task_statuses/{id}/restore — Restore an archived one of project_task_statuses GET /v1/project_task_types — List project_task_types POST /v1/project_task_types — Create one of project_task_types POST /v1/project_task_types/query — List project_task_types, parameters in the body GET /v1/project_task_types/{id} — Get one of project_task_types PATCH /v1/project_task_types/{id} — Update one of project_task_types DELETE /v1/project_task_types/{id} — Archive one of project_task_types POST /v1/project_task_types/{id}/restore — Restore an archived one of project_task_types GET /v1/project_role_types — List project_role_types POST /v1/project_role_types — Create one of project_role_types POST /v1/project_role_types/query — List project_role_types, parameters in the body GET /v1/project_role_types/{id} — Get one of project_role_types PATCH /v1/project_role_types/{id} — Update one of project_role_types DELETE /v1/project_role_types/{id} — Archive one of project_role_types POST /v1/project_role_types/{id}/restore — Restore an archived one of project_role_types GET /v1/project_task_role_types — List project_task_role_types POST /v1/project_task_role_types — Create one of project_task_role_types POST /v1/project_task_role_types/query — List project_task_role_types, parameters in the body GET /v1/project_task_role_types/{id} — Get one of project_task_role_types PATCH /v1/project_task_role_types/{id} — Update one of project_task_role_types DELETE /v1/project_task_role_types/{id} — Archive one of project_task_role_types POST /v1/project_task_role_types/{id}/restore — Restore an archived one of project_task_role_types GET /v1/deliverable_statuses — List deliverable_statuses POST /v1/deliverable_statuses — Create one of deliverable_statuses POST /v1/deliverable_statuses/query — List deliverable_statuses, parameters in the body GET /v1/deliverable_statuses/{id} — Get one of deliverable_statuses PATCH /v1/deliverable_statuses/{id} — Update one of deliverable_statuses DELETE /v1/deliverable_statuses/{id} — Archive one of deliverable_statuses POST /v1/deliverable_statuses/{id}/restore — Restore an archived one of deliverable_statuses GET /v1/signal_statuses — List signal_statuses POST /v1/signal_statuses — Create one of signal_statuses POST /v1/signal_statuses/query — List signal_statuses, parameters in the body GET /v1/signal_statuses/{id} — Get one of signal_statuses PATCH /v1/signal_statuses/{id} — Update one of signal_statuses DELETE /v1/signal_statuses/{id} — Archive one of signal_statuses POST /v1/signal_statuses/{id}/restore — Restore an archived one of signal_statuses GET /v1/signal_types — List signal_types POST /v1/signal_types — Create one of signal_types POST /v1/signal_types/query — List signal_types, parameters in the body GET /v1/signal_types/{id} — Get one of signal_types PATCH /v1/signal_types/{id} — Update one of signal_types DELETE /v1/signal_types/{id} — Archive one of signal_types POST /v1/signal_types/{id}/restore — Restore an archived one of signal_types GET /v1/signal_severities — List signal_severities POST /v1/signal_severities — Create one of signal_severities POST /v1/signal_severities/query — List signal_severities, parameters in the body GET /v1/signal_severities/{id} — Get one of signal_severities PATCH /v1/signal_severities/{id} — Update one of signal_severities DELETE /v1/signal_severities/{id} — Archive one of signal_severities POST /v1/signal_severities/{id}/restore — Restore an archived one of signal_severities GET /v1/signal_probabilities — List signal_probabilities POST /v1/signal_probabilities — Create one of signal_probabilities POST /v1/signal_probabilities/query — List signal_probabilities, parameters in the body GET /v1/signal_probabilities/{id} — Get one of signal_probabilities PATCH /v1/signal_probabilities/{id} — Update one of signal_probabilities DELETE /v1/signal_probabilities/{id} — Archive one of signal_probabilities POST /v1/signal_probabilities/{id}/restore — Restore an archived one of signal_probabilities