API
This section describes the runtime API: routes, request shapes, file handling, trigger webhooks, and error codes.
Base URL: https://app.monkedo.com
Every request requires a valid API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYA key can only access components you explicitly enabled when configuring the key. Requests for anything else are rejected.
The key's connection is applied automatically. Do not send _connection in inputs. Component schemas returned by the API omit that field.
Endpoints
Section titled EndpointsEvery request requires a valid API key in the Authorization header.
A key can only access components you explicitly enabled when configuring the key. Requests for anything else are rejected.
List Available Applications
GET /api/v1/components/appsList apps this key can use.
Query Parameters
Name | Type | Default | Description |
|---|---|---|---|
onlyEnabled | Boolean |
| When |
200: OK
[
{
"name": "Cubicl",
"icon": "cubicl.png",
"key": "cubicl"
},
{
"name": "Email",
"icon": "trigger/email.png",
"key": "email"
}
]Get Component Definitions
GET /api/v1/components/listReturn definitions (inputs, outputs, descriptions) for all components this key may use.
Query Parameters
Name | Type | Description |
|---|---|---|
appKey | String | Optional. Limit the list to one app (e.g. |
200: OK
[
{
"id": "action.cubicl.get-client",
"name": "Get Client",
"desc": "Gets client details. [See the docs here](https://docs.cubicl.io/api-integration/clients#get-client-by-id).",
"appKey": "cubicl",
"appName": "Cubicl",
"icon": "cubicl.jpg",
"isTrigger": false,
"inputs": {
"clientId": {
"title": "clientId",
"description": "The ID of the client to be retrieved.",
"type": "string"
}
},
"outputs": {
"client": {
"title": "client",
"type": "object",
"properties": {}
}
},
"inputsWithQueryableOptions": [],
"required": ["clientId"]
}
]inputs and outputs are JSON Schema. File fields use the shapes described in Files below.
inputsWithQueryableOptions lists input names whose option lists can be loaded through Get Dynamic Input Options. Only present when at least one input supports dynamic options.
Get Component Details
GET /api/v1/components/details/:componentKeyReturn the full definition for one component, in the same JSON Schema format as the list endpoint.
Path Parameters
Name | Type | Description |
componentKey* | String | Component id — e.g. |
200: OK
// Same object shape as one item from GET /api/v1/components/list.Get Dynamic Input Options
POST /api/api-keys/input-optionsLoad the option list for a component input whose choices depend on other inputs (for example, a project list that changes after you pick an account).
Use inputsWithQueryableOptions from the component definition to see which input names support this endpoint.
Body
Name | Type | Description |
|---|---|---|
componentId* | String | Component id — e.g. |
inputName* | String | Input whose options you want — e.g. |
inputs | Object | Values of inputs that appear before |
search | String | Optional filter text for searchable option lists |
200: OK
[
{ "value": "GROUP_ID_1", "label": "My Project 1", "desc": "GROUP_ID_1" },
{ "value": "GROUP_ID_2", "label": "My Project 2", "desc": "GROUP_ID_2" },
]The API key's configured connection is used automatically when the component requires authentication.
Create File Upload Link
POST /api/v1/files/upload-linkReserve a file and get a presigned upload URL. Use this for large files instead of sending base64 in Run Component.
Body
Name | Type | Description |
|---|---|---|
name* | String | File name including extension. Cannot contain |
200: OK
{
"fileId": "507f1f77bcf86cd799439011",
"s3Name": "507f1f77bcf86cd799439011-report.pdf",
"uploadUrl": "https://..."
}POSTthis endpoint to getuploadUrlandfileId.PUTthe file bytes touploadUrl.Pass
{ "name": "report.pdf", "fileId": "507f1f77bcf86cd799439011" }as the file input when running a component.
Files uploaded this way are not subject to the 100 MB limit that applies to base64 and URL inputs.
The presigned URL expires after 15 minutes.
Run Component
POST /api/v1/components/:componentId/runExecute an action.
Path Parameters
Name | Type | Description |
componentId* | String | Component id — e.g. |
Body
Name | Type | Description |
inputs* | Object | Component inputs. Omit |
200: OK
{
"name": "Result name",
"outputs": {
"result": "VALUE"
},
"componentId": "action.misc.logger",
"creditsUsed": 1
}outputs contains raw values, File outputs are { name, size, url }. Paid components may consume credits from your team's balance.
List Registered Triggers
GET /api/v1/components/triggers200: OK
[
{
"_id": "6a295afb530d2213967340c1",
"componentId": "trigger.cubicl.task-archived",
"inputs": {
"group": "GROUP_ID"
},
"createdAt": "2026-06-10T12:39:23.183Z",
"webhookUrl": "https://hooks.example.com/listen"
}
]Register Trigger
POST /api/v1/components/triggersRegister a trigger. When it fires, Monkedo POSTs JSON to webhookUrl:
{
"triggerId": "6a296203f6dd56f7cd1d4313",
"componentId": "trigger.cubicl.task-created",
"success": true,
"outputs": {
"task": { }
}
}File values inside outputs use { name, size, url }, same as run results.
Body
Name | Type | Description |
componentKey* | String | Trigger component id — e.g. |
webhookUrl* | String | Absolute public HTTP(S) URL. Localhost and private IPs are rejected. |
inputs | Object | Trigger register parameters (varies by component). |
200: OK
{
"triggerId": "6a296203f6dd56f7cd1d4313"
}webhookUrl must be reachable from the internet. For local development, use a tunnel such as NGROK.
Polling vs webhook triggers
Your webhookUrl is always how you receive events. The difference is how Monkedo learns that something happened in the app:
Webhook triggers | Polling triggers | |
|---|---|---|
How Monkedo is notified | The app calls Monkedo as soon as the event happens | Monkedo checks the app on a schedule |
When you get the POST | Usually within seconds | After the next poll — there can be a delay |
What is reported | The event that just occurred | New items found since the last check (typically only after the trigger was registered) |
Unregister Trigger
DELETE /api/v1/components/triggers/:triggerIdRemove a trigger. Returns 404 if the trigger does not belong to this key.
Path Parameters
Name | Type | Description |
triggerId* | String | Registered trigger id |
200: OK
// EmptyFiles
Section titled FilesFile inputs (including List<File>, such as Send Email attachments):
{
"name": "note.txt",
"base64": "SGVsbG8="
}or a public download URL:
{
"name": "note.txt",
"url": "https://example.com/note.txt"
}or a file reserved through Create File Upload Link:
{
"name": "note.txt",
"fileId": "507f1f77bcf86cd799439011"
}Rules:
nameis required and must include the extension. It cannot contain/,\, or:.Provide
base64,url, orfileId. If bothbase64andurlare set,base64is used.Max size is 100 MB for
base64andurlinputs. ThefileIdpath has no 100 MB cap.urlmust be public HTTP(S). Localhost and private IPs are rejected.
File outputs (run results and trigger webhooks):
{
"name": "report.pdf",
"size": 2048,
"url": "https://monkedo.s3.<region>.backblazeb2.com/<object>"
}Errors
Section titled ErrorsErrors are returned as JSON with an HTTP status code:
{
"statusCode": 403,
"message": "Invalid API key.",
"error": "Forbidden"
}Authentication (403 Forbidden)
Message | Meaning |
|---|---|
API key not provided or malformed. | Missing header or incorrect Bearer format |
Invalid API key. | Key is wrong, deleted, or regenerated |
Authorization (403 Forbidden)
Message | Meaning |
|---|---|
the component you are trying to run is not enabled for this api key… | Component not enabled on this key — update the key in the dashboard |
API key does not have access to component '…' | Trigger component not enabled on this key |
API key does not have access to this component | Dynamic input-options request for a component not enabled on this key |
Not found (404)
Message | Meaning |
|---|---|
API key not found | Key ID invalid or not in your team |
Component '…' not found or not allowed | Unknown component or not enabled on this key |
Trigger '…' not found or not owned by this API key | Trigger missing or belongs to another key |
Validation (400 Bad Request)
Message | Meaning |
|---|---|
Connection not found for app … | Linked account is missing or invalid |
App … requires a SMTP/IMAP connection but none was provided. | Multi-auth app (e.g. Email) is missing a required connection |
An app has a connection but no components are selected… | Connection set but no components chosen |
webhookUrl is required | Trigger register body omitted |
webhookUrl must be an absolute HTTP(S) URL | Not a valid |
Localhost and private IP addresses are not supported… | Webhook or file URL is not public |
File input must be an object with name and either base64 or url. | File field is not |
File name is required. | Missing |
File name cannot include /, , or :. | Invalid file name |
File "…" needs base64 contents or a public url. | Neither |
File id "…" is not valid. |
|
File "…" was not found in this team. |
|
File size is too large. Max size is 100 MB. | File exceeds the limit (base64/url path only) |
File base64 contents are not valid. |
|
File URL is not accessible. | Download from |
Input "…" must be an array of files. | A |
Invalid component id | Unrecognized component ID |
inputName is required. | Dynamic input-options body omitted |
Input '…' does not exist on this component. | Unknown input name |
Input '…' does not support dynamic options. | Input is not queryable |
No connection configured on this API key for app '…' | Auth required but key has no connection for that app |
INVALID_NODE_CONNECTION | Linked account expired or revoked at runtime |
Runtime failures
Status | Meaning |
|---|---|
400 | Invalid or incomplete inputs |
422 | The action ran but failed (e.g. upstream API error) |
500 | Unexpected server error — contact support if it persists |
Examples
Section titled ExamplesReplace YOUR_API_KEY with your secret.
# List apps enabled on this key
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://app.monkedo.com/api/v1/components/apps
# List Email components only
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://app.monkedo.com/api/v1/components/list?appKey=email"
# Load dynamic options for an input
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"componentId": "action.cubicl.get-tasks", "inputName": "group", "inputs": {}}' \
https://app.monkedo.com/api/api-keys/input-options
# Reserve a large file upload
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "large-video.mp4"}' \
https://app.monkedo.com/api/v1/files/upload-link
# Run an action
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {"getOnlyNames": true, "limit": 50, "skip": 0}}' \
https://app.monkedo.com/api/v1/components/action.cubicl.get-clients/run
# Send email with a file attachment
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": {
"to": ["user@example.com"],
"subject": "File Test",
"body": "Hello",
"saveToSent": false,
"attachments": [{ "name": "note.txt", "base64": "SGVsbG8=" }]
}
}' \
https://app.monkedo.com/api/v1/components/action.email.send-email/run
# Register a trigger (events are POSTed to webhookUrl)
curl -X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"componentKey": "trigger.cubicl.task-created",
"webhookUrl": "https://hooks.example.com/listen",
"inputs": { "group": "GROUP_ID" }
}' \
https://app.monkedo.com/api/v1/components/triggers