Skip to main content

Public API

Create and manage Evo Researcher projects from code

B
Written by Bianca Manase

You can use the Evo Researcher public API to create and manage projects, templates, apps and chats from your own systems and integrations.

The Evo Researcher public API lets other Evo products and integrations work with Researcher from code. You can create projects, hand over conversations from other AI tools, and manage templates, apps, skills, collaborators and chats. This article explains how to get started and where to find each task.


Before you start

Make sure you have the following before you make your first request.

  • A button token for your integration. You send it with every request.

  • The role for the task you need. Creating or updating templates and organisation skills needs the org_author role. Listing users and managing other people's roles needs the admin role.

  • Write access to any project you want to change. Only the project owner can delete a project or manage its collaborators.

A request from an inactive user or organisation returns 403. A missing or invalid token returns 401.


Authenticate and choose your environment

Choose the base URL for your environment, then add your token to each request.

  1. Choose the base URL for your environment from the table.

  2. Add an Authorization header to each request. Set its value to Bearer followed by your button token.

  3. For requests with a body, set Content-Type to application/json.

All endpoint paths in this article are relative to your base URL. For example, POST /projects in Production UK is sent to the Production UK base URL followed by /projects.

Keep your button token secret. Store it in your integration's secure configuration, not in code that others can read.


Create a project

You can create a project with only a name, or set up its template, instructions and chat history in one request.

Required conditions: Supply a name, a template_id, or both. If you leave out the name, you must supply a template_id, and Researcher names the project after the template with a timestamp.

  1. Send a POST request to /projects.

  2. Set name to the display name. The limit is 200 characters.

  3. Add any optional fields you need from the table below.

  4. Save the id and chat_id from the response. Use the chat_id to take the user straight into the conversation.

Optional field

Limit or format

What it does

description

2,000 characters

Describes the project.

system_prompt

10,000 characters

Sets the instructions the project follows.

template_id

Template UUID

Applies the template's instructions, uploads, connectors and settings.

folder_id

Folder UUID

Places the project in a folder.

tag_id

Tag UUID

Attaches a tag when the project is created.

actions

Up to 50 action names

Adds actions to the project.

output_schema

JSON Schema

Turns each chat turn into a validated JSON artifact.

messages

Up to 500 items

Pre-fills the chat history. Each item needs a role and content.

Hand over a conversation from another AI product

If an AI chatbot passes a user to Researcher, send the conversation so far in the messages field. Each message needs a role of user or assistant, and content of up to 100,000 characters. Researcher sets the chat title from the first user message, so the user can carry on where they left off.


Work with templates

Templates provide the starting setup for a project, including its instructions, uploads, connectors and settings. A project takes a copy of its template when it is created, so editing a template does not change projects that already exist.

Task

Method and path

Who can use it

List organisation templates

GET /templates

Any signed-in user

Get one template

GET /templates/{templateId}

Any signed-in user

Create a template

POST /templates

Users with the org_author role

Update a template

PATCH /templates/{templateId}

Users with the org_author role

List your personal templates

GET /templates/personal

You

Get one personal template

GET /templates/personal/{id}

You

Create or update a template

  1. To create a template, send a POST request to /templates with a name. You can also add a description, system_prompt, on_launch_message, on_launch_prompt, icon and colour.

  2. To update a template, send a PATCH request to /templates/{templateId} with only the fields you want to change. Any field you leave out stays the same.

You cannot set a template's connectors, agents, knowledge spaces, actions or collaborators through the API. Configure these in Evo Researcher. Because updates never clear them, an update cannot remove this setup.

You can read your own personal templates through the API, but you cannot create, update or delete them there. Manage them in Evo Researcher.


Manage apps

An app is a template published to Navigator. It can appear as a Quick Panel, a Quick Action or a Quick Section, and it opens a focused Researcher experience. Apps start as drafts and go live only when you publish them.

Required conditions: Build each app on an organisation template. Use List Templates to find its id. A personal template id is rejected, because a published app is visible across the organisation.

  1. Send a POST request to /apps with a title, description, colour, one surface and params. The app is saved as a draft.

  2. Save the id from the response.

  3. Send a PUT request to /apps/{id}/publish to make the app live in Navigator.

Choose where the app appears

Choose exactly one surface:

  • quickPanel: set to true to appear as a Quick Panel.

  • quickAction: set to an object with a width of small, medium or large.

  • quickSection: set to an object with a size of small, medium or large.

Set mobile to true if you also want the app in the Evo mobile app. It appears on desktop web only by default.

Choose one of these colours: teal, purple, nileblue, ceruleanblue, bluelagoon, eaglegreen, sapgreen, burntorange, brickred, accessred, electricviolet or blueviolet.

Set the app parameters

The params object controls how the app behaves:

  • version must be 2.

  • templateId is the organisation template the app is built on.

  • style is standard for the normal product look, or chatbot for a stripped-back chat style.

  • launch sets the surface the app opens on. It is chat by default.

  • chat, conversations and features each take a show value of true or false.

A chatbot-style app usually turns off most features and leads with chat. A full-workspace app turns them on.

Control who can see the app

By default, a published app is visible to the whole organisation. To narrow access, set security to one of these:

  • Specific users, using up to 100 user ids.

  • Specific groups, where each group has a type of basic or smart.

Set one target only. You can set access on a draft, and it takes effect when you publish.

Other app tasks

Task

Method and path

List apps, including drafts

GET /apps

Update an app

PUT /apps/{id}

Unpublish an app

PUT /apps/{id}/unpublish

Delete an app

DELETE /apps/{id}

App fields use camelCase, such as quickAction and templateId. Projects and chats use snake_case, such as template_id.

⚠️Warning: Updating a published app changes it live in Navigator straight away. The update replaces the whole app definition, so send every field you want to keep.


Organise and update projects

Folders belong to the user who creates them, and you can nest them.

Task

Method and path

Notes

List your folders

GET /folders

Each folder includes a parent_id, so you can rebuild the hierarchy.

Create a folder

POST /folders

Send a name and an optional parent_id. Folder names must be unique among sibling folders.

List projects

GET /projects

Search with q, and filter with folderId or tag. Use page and limit to paginate.

Get project details

GET /projects/{projectId}

Shows connectors, artifacts, uploads and the system prompt.

Update a project

PATCH /projects/{projectId}

Changes the name, description or system_prompt. Send an empty system_prompt to clear it.

Set the output schema

PUT /projects/{projectId}/output-schema

Send null to turn structured output off.

Delete a project

DELETE /projects/{projectId}

Only the owner can delete a project.

When you update a project, include only the fields you want to change.

⚠️Warning: Deleting a project is permanent. Its chats, uploads, artifacts, attached skills and connectors are deleted with it. There is no way to recover it.


Share projects with collaborators

Collaborators are existing Researcher users in your organisation. You choose whether each one can view the project or also change it.

Required conditions: You must own the project. To find a user's id, use GET /users, which needs the admin role.

  1. Send a POST request to /projects/{projectId}/collaborators with the user_id and an access_level of read or read_write.

  2. Check the list with GET /projects/{projectId}/collaborators.

  3. To change someone's access, send a PATCH request to /projects/{projectId}/collaborators/{userId}.

  4. To stop sharing, send a DELETE request to the same path. The project itself is not affected.

A collaborator can remove themselves from a shared project. Anyone else needs the owner to remove them.

Your organisation's administrator sets a collaboration policy that limits sharing.

  • Full: you can share at either access level.

  • Read only: you can share at read level only. Granting read_write returns 403.

  • Off: sharing is switched off, so adding or changing a collaborator returns 403.

Existing collaborators keep their access if the policy changes, and you can always remove them.


Add skills and connectors

A skill is a reusable set of instructions. Organisation skills belong to your whole organisation, and personal skills belong to you. Only skills with a binding type of project can be attached to a project.

Task

Method and path

List a project's skills

GET /projects/{projectId}/skills

Attach a skill

POST /projects/{projectId}/skills/{skillId}

Detach a skill

DELETE /projects/{projectId}/skills/{skillId}

List organisation skills

GET /skills/organisation

Create, update or delete an organisation skill

POST, PATCH or DELETE on /skills/organisation or /skills/organisation/{id}

Personal skills use the same paths under /skills/personal.

Attaching a skill that is already attached returns the existing attachment, so it is safe to repeat. Detaching a skill does not delete it from the library.

Attach a connector

You can attach two types of connector through the API: Evo product connectors and third-party connectors. Agent and custom (MCP) connectors cannot be changed through the API.

  1. Find the connector's route in the connectors catalogue.

  2. Send a POST request to the matching path:

    • Evo product connector: /projects/{projectId}/evo-product-connectors, with a route. You can also add an instance_id and instance_name.

    • Third-party connector: /projects/{projectId}/third-party-connectors, with a route.

  3. To remove a connector, get its record id from GET /projects/{projectId}. Then send a DELETE request to the matching path with that id.

Attaching a connector that is already attached on the same route returns 409.


Tag projects

Tags help you filter and organise projects. The API cannot list or create tags, so get the tag id from your own system.

  1. Send a POST request to /projects/{projectId}/tags with the tag_id.

  2. To remove the tag, send a DELETE request to /projects/{projectId}/tags/{tagId}.

  3. To find tagged projects, send GET /projects with the tag filter.

Attaching a tag that is already attached, or removing one that is not, has no effect.


Upload files and query datasets

You can add files to a project and query spreadsheet data directly. Each file must be 30 MB or smaller.

Supported file types are .txt, .json, .csv, .md, .pdf, .docx, .xlsx, .xls, .pptx, .html, .xml, .rtf, .yaml, .yml and .log.

  1. Convert the file to base64.

  2. Send a POST request to /projects/{projectId}/uploads with the filename, mimeType, size in bytes and content.

  3. Check GET /projects/{projectId}/uploads/{uploadId} until the status changes from processing to ready. If it shows error, the response explains why.

Task

Method and path

List uploads

GET /projects/{projectId}/uploads

Download the original file

GET /projects/{projectId}/uploads/{uploadId}/download

Get a temporary download link

GET /projects/{projectId}/uploads/{uploadId}/blob-url

Delete an upload

DELETE /projects/{projectId}/uploads/{uploadId}

Use the download endpoint when your code needs the file itself. Use the blob-url endpoint for an iframe, an image or a link. Temporary links expire after about 5 minutes.

Query a dataset

Spreadsheets become structured datasets. A CSV file produces one dataset, and an Excel file produces one dataset per sheet.

  1. Send GET /projects/{projectId}/datasets to find the dataset id.

  2. Send a POST request to /projects/{projectId}/datasets/{datasetId}/query with the filters, groupBy, aggregations and orderBy you need.

Each query works on a single dataset, and you cannot join datasets. A query returns 100 rows by default, up to 5,000 rows per response. If more rows exist, use the cursor from the response to get the next page.


Read and create artifacts

Artifacts are the files and documents a project generates. Each artifact has one of these types: HTML, PDF, EXCEL, MARKDOWN, MFE, CHART or POWERPOINT.

Task

Method and path

List artifacts

GET /projects/{projectId}/artifacts

Get metadata and text content

GET /projects/{projectId}/artifacts/{artifactId}

Get full content

GET /projects/{projectId}/artifacts/{artifactId}/content

Download the file

GET /projects/{projectId}/artifacts/{artifactId}/download

Get a temporary link

GET /projects/{projectId}/artifacts/{artifactId}/blob-url

Upload an artifact

POST /projects/{projectId}/artifacts

To upload an artifact, send its name, its type and its content as base64. The limit is 30 MB.

The API stores the bytes you upload exactly as sent. It does not check that the file matches the type you declare.

PowerPoint artifacts do not support the blob-url endpoint. Use the download endpoint instead.


Run chats in a project

Use the start, poll and fetch pattern for background jobs, such as scheduled reports. Use streaming when a person is waiting for the reply.

Run a chat in the background

  1. Send a POST request to /projects/{projectId}/chats/start with a message. You receive a chat_id and a status of generating.

  2. Check GET /projects/{projectId}/chats/{chatId} until the status is no longer generating.

  3. Send GET /projects/{projectId}/chats/{chatId}/messages to read the full transcript.

To stop a chat that is still running, send a POST request to /projects/{projectId}/chats/{chatId}/cancel. Then check the status until it shows cancelled or idle.

While you check the status, watch message_count. When it goes up, a new reply has arrived.

Stream a reply

Send a POST request to /projects/{projectId}/chats/stream with an id for the message and a message object that contains the role user and the text parts. The reply arrives as Server-Sent Events. If the connection drops, reconnect with GET /projects/{projectId}/chats/{chatId}/stream. This returns 204 when no stream is active.

To list the chats in a project, send GET /projects/{projectId}/chats.


Use standalone chats

Standalone chats sit outside a project, so they suit short, one-off conversations.

Task

Method and path

Create a chat

POST /chats

List your chats

GET /chats

Get one chat

GET /chats/{id}

Stream a message

POST /chats/{id}/stream

Work with uploads

/chats/{id}/uploads and /chats/{id}/uploads/{uploadId}

Work with artifacts

/chats/{id}/artifacts and /chats/{id}/artifacts/{artifactId}

When you create a chat, every field is optional. You can add a name, a template_id, actions and messages. A chat can use one template only, and you cannot change it later.

Standalone chats have no transcript endpoint. You also cannot rename, delete or favourite them through the API.


Choose a response preset

A preset is a named model with the settings Researcher runs it with. Presets stay the same even when the model behind them changes, so your integration does not need to change.

  1. Send GET /llm/presets to see the presets you can use and your preferred preset.

  2. Add the preset id to your request.

A chat keeps the preset from its first turn, so you only need to set it once. If you ask for a preset you cannot use, the request returns 400 with the code PRESET_NOT_AVAILABLE. Researcher never swaps in a different preset. The older model field still works, but preset takes priority if you send both.


Approve tool calls

By default, chats started through the API approve every tool call they make. To pause write-type tool calls for approval, set enable_tool_consent to true when you start or stream a chat. Read-only calls are never paused. The setting is remembered for that chat.

  1. Start the chat with enable_tool_consent set to true.

  2. Check GET /projects/{projectId}/chats/{chatId}. The pending_tool_consent field shows the tool name and a request_id.

  3. Send a POST request to /projects/{projectId}/chats/{chatId}/tool-consent/{requestId}/decision with a decision of allow, deny or always_allow.

Choosing always_allow approves future calls of the same tool and operation in that project, so Researcher stops asking.

If nobody answers a pending request within a few minutes, Researcher denies it automatically and the turn continues.


Ask the AI without a project or chat

Use the LLM endpoints when you need one answer inside a wider workflow, such as classifying a support ticket or summarising a paragraph. Researcher stores nothing from these calls.

Task

Method and path

Response

Get a finished answer

POST /llm/message

JSON, once generation completes

Stream an answer

POST /llm/stream

Server-Sent Events, while the model writes

Both endpoints take the same body. Include a message, up to 100,000 characters. You can also add messages (earlier turns, up to 500), a system_prompt, a preset and tools.

⚠️Important: Researcher keeps no memory between calls. Send the earlier turns in messages every time.

To let the model search the web, set tools to an object with web_search set to true. Web search works only on presets whose model has built-in search. On any other preset, the request returns 400 with the code TOOL_NOT_AVAILABLE. Retry without web search, or choose a different preset.


Manage user roles

Only admins can read other users' roles or grant and revoke them. Anyone can read their own roles by using me as the user id.

Role

What it allows

Can you grant it through the API?

org_author

Create and manage organisation templates and skills

Yes

org_settings

Change organisation settings

Yes

app_author

Create, edit and delete apps

Yes

app_publisher

Publish and unpublish apps

Yes

admin

Organisation admin

No. Access manages this role.

user

Standard access

No. Applied to all users.

  1. Find the user's id with GET /users. You can search by name or email with q.

  2. To grant a role, send a POST request to /users/{userId}/roles/{role}.

  3. To remove a role, send a DELETE request to the same path.

  4. Check the result with GET /users/{userId}/roles.

Granting a role the user already has, or revoking one they do not have, has no effect.


Send messages to an embedded Researcher

If your product embeds Researcher, your host can send messages into the open chat.

  1. Call the executeMfeFunction method from the Evo host SDK.

  2. Pass the instance id you used when you embedded Researcher, the function name sendMessage, and a text value.

Researcher treats the message as if the user typed it. If a reply is still streaming, new messages queue and send in the order they arrived. Blank text is ignored. The call resolves once Researcher accepts the message, not when the reply finishes.


Fix common errors

Status

What it means

What to do

400

The request is invalid, such as a missing field or a value over its limit.

Check the message in the response and correct the request.

401

The token is missing, invalid or lacks the required scope.

Check your button token and its scopes.

403

The account or organisation is inactive, or you lack the role or access needed.

Check your permissions with your administrator.

404

The item does not exist or is not visible to you.

Check the id. Other users' private items also return 404.

409

The request clashes with the current state, such as a duplicate connector or a chat waiting for a consent decision.

Check the current state, then try again.

503

Generation failed upstream, for example because of rate limiting.

Wait a moment, then retry.

Did this answer your question?