Build with Softools.

Use the Softools public API to read and update app data, access View reports, and work with images and documents. Connect AI assistants to published Views through the Model Context Protocol (MCP).

Explore the Swagger API Download OpenAPI JSON Connect using MCP

REST API authentication

Send REST API requests to https://api-gateway.softools.net. Include both headers with every authenticated REST API request:

ApiKey: <your user API key>
Tenant: <your tenant identifier>

The API key is user-specific, so record creation and updates retain the correct audit identity. Rotate it from your Softools user profile if it may have been exposed.

Use Views to read data

For new integrations, use Get View and Get View Record rather than the direct single-record or list APIs. Views return the fields defined in the selected View report and support higher request limits: 120 calls per minute, compared with 10 for a direct single-record read and 5 for a direct list read.

Choose a View report for your integration and use its identifier as ViewReportIdentifier. Ask your app administrator which app and View identifiers to use.

Read records from a View:
GET /Api/Apps/{AppIdentifier}/View/{ViewReportIdentifier}

Read one record through a View:
GET /Api/Apps/{AppIdentifier}/View/{ViewReportIdentifier}/Record/{RecordId}

Use these paths on https://api-gateway.softools.net with your ApiKey and Tenant headers. See Swagger for query options and response schemas. The direct data APIs remain available for existing integrations; use the write APIs when creating or updating records.

Connect AI assistants through Views

Softools supports the Model Context Protocol (MCP), so Claude, Microsoft Copilot Studio, and other compatible clients can discover and query published Views as read-only tools. App Builders choose which Views to expose; each View defines the fields available to the assistant.

Connect your MCP client using Streamable HTTP:
https://api-gateway.softools.net/mcp/{tenant}

Replace {tenant} with your Softools tenant identifier, or copy the MCP endpoint shown in App Studio.

  1. In App Studio, open the app's Reports, edit a View, and enable Expose this published View as an MCP tool. Save and publish the app.
  2. An Advanced App Builder opens Configure > MCP connections and approves a trusted client's published identity (CIMD), automatic registration (DCR), or manual public client. Approval binds exact HTTPS callback URLs to this tenant. For Claude, use its published callback https://claude.ai/api/mcp/auth_callback. For CIMD, also enter the exact client metadata URL supplied by the client. A client name or registration alone grants no tenant access.
  3. In Claude, open Customize > Connectors > Add custom connector, paste the MCP endpoint, and select Sign in now. Select Use Claude's published identity for an approved CIMD profile, Register automatically for an approved DCR profile, or Use your own OAuth client and the generated public client ID for a manual profile. Leave the client secret blank. For Team or Enterprise, an organization owner can add the connector centrally under Organization settings > Connectors.
  4. Employees connect using their own Softools sign-in. Each user needs a Softools account with permission to access the app, View, and records they want to query.

New MCP connections discover the Softools OAuth broker and use authorization code flow with PKCE S256. Users sign in with the tenant's configured provider and consent to read access; provider credentials stay on the server. Broker tokens apply only to MCP, with the exact tenant endpoint as their audience. Access tokens last 15 minutes. The offline_access scope enables rotating refresh tokens, with a seven-day absolute grant lifetime. Reusing a code or refresh token revokes its grant. Reconnect after expiry or revocation.

For clients supporting manual public OAuth, use the public client ID from App Studio, authorization URL /mcp/oauth/authorize, token/refresh URL /mcp/oauth/token and scopes mcp:read offline_access on the public gateway. A compatible client must send the exact MCP URL in the OAuth resource parameter and use PKCE S256. In Copilot Studio, select OAuth 2.0 → Dynamic discovery and approve its exact callback URL as a dynamic client in App Studio.

Tools include View and field descriptions, plus references to related exposed Views in connected apps. Give Views and fields clear descriptions to help assistants choose the right data. A child app needs its own published MCP-enabled View for its records to be queried independently; child values included in a parent View remain available through that parent View.

Each tool's input schema documents typed filters, supported operators, sorting, parent-record queries and cursor pagination. Filters combine with AND; use in for alternative values on one field. For checkbox/listbox fields, eq means contains the selection, ne means does not contain it, and in means contains any supplied selection. Use field identifiers and scalar selection values, not field labels or selection output objects.

Call get_current_user with no arguments to get {"userId":"<Softools user ID>"} for the signed-in user. For requests such as "assigned to me", use that ID in an eq filter on an exposed View field that stores Softools user IDs. This tool is available even when no Views are exposed and does not enable filtering on additional fields.

App context resources provide published app and View descriptions, exposed field terminology and accessible parent/child app relationships. Clients can discover them with resources/list and read them with resources/read. Set includeContext: true on a View query to receive the context as an embedded resource alongside the normal records, including in clients such as Copilot Studio that consume resources through tool outputs. Context is optional and scoped to the user's accessible MCP-enabled Views; it does not expose unpublished configuration. Republish existing apps to populate their app-level description in older published snapshots.

MCP returns active records using the existing View JSON format and respects the signed-in user's permissions. Archived queries and record updates are not supported through MCP. Publish configuration changes before expecting them to appear in connected assistants.

When Data Lens is enabled for a published app, every MCP-exposed View also gets a semantic search tool. Search tools return ranked active records with that View's fields. Use semantic search for natural-language matches; use the View query tool for exact filters, sorting and record lookup. A lower distance means a closer match. Search has no stable pagination and is limited to 10 calls per minute per user and app.

Search View records by meaning

Enable Data Lens in App Studio and publish the app. Then call GET /Api/Apps/{AppIdentifier}/View/{ViewReportIdentifier}/Search on the REST API with your API key and tenant headers. The View chooses which fields are returned; REST use does not require the View's MCP exposure setting.

GET /Api/Apps/{AppIdentifier}/View/{ViewReportIdentifier}/Search?$search=hotel%20stay&$top=10

$search is required. $top defaults to 10 and accepts 1 to 40; an optional $filter narrows matches using an OData expression. Results contain recordId, distance, and the projected record. Lower distance means a closer semantic match. Records still need to be accessible to the signed-in user. Search results can change as data and embeddings update, so repeated requests are not a paging mechanism. See Swagger for the response schema and errors.

REST API fair-use rate limits

RequestPartitionLimit
Get View (including archived)Per user, per app120 calls per minute
Get View Record (including archived)Per user, per app, per record120 calls per minute
Data Lens View searchPer user, per app10 calls per minute
Get a single record directlyPer user, per app, per record10 calls per minute
Get many records directlyPer user, per app5 calls per minute
Patch or post a recordPer user, per app50 MB per 5 minutes
Patch using CSVPer user, per app50 MB per 5 minutes

A request over its limit returns 429 Too Many Requests with a Retry-After header giving the number of seconds to wait, and a JSON body with the same number of seconds:

{"statusCode":429,"message":"Rate limit is exceeded. Try again in 60 seconds."}